I'm trying to write the stretch goals of chapter 13 in the book
In particular:
To fix this issue, try introducing more generic parameters to increase the flexibility of the
Cacher
functionality.
I have the following definition of Cacher
which I was pretty happy with. I made it generic on functions with different input and output types, but there's a problem, this code won't compile:
pub struct Cacher<F,U,V>
where F: Fn(U) -> V, U: Copy
{
calculation: F,
value: Option<V>,
}
impl<F,U,V> Cacher<F,U,V>
where F: Fn(U) -> V, U: Copy
{
pub fn new(calculation: F) -> Cacher<F,U,V> {
Cacher {
calculation,
value: None,
}
}
pub fn get(&mut self, arg: U) -> V {
match self.value {
Some(v) => v,
None => {
let v = (self.calculation)(arg);
self.value = Some(v);
v
}
}
}
}
compilation error:
error[E0392]: parameter `U` is never used
--> src/structs.rs:3:21
|
3 | pub struct Cacher<F,U,V>
| ^ unused parameter
|
= help: consider removing `U`, referring to it in a field, or using a marker such as `std::marker::PhantomData`
Which leads me to std::marker::PhantomData
, from reading this I gather that PhantomData is used to guide the type-checker where it can't "figure out stuff" on its own.
But it also led me to believe that the PhantomData
isn't really there at all. In the examples, struct fields are prefixed with _
, which usually means ignore this bit.
So then y question (finally, thanks for reading this far) is why does the compiler enforce PhantomData fields be defined when making the struct?:
use std::marker::PhantomData;
pub struct Cacher<F,U,V>
where F: Fn(U) -> V, U: Copy
{
calculation: F,
value: Option<V>,
_phantom: PhantomData<U>,
}
gives the error:
error[E0063]: missing field `_phantom` in initializer of `structs::Cacher<_, _, _>`
--> src/structs.rs:15:9
|
15 | Cacher {
| ^^^^^^ missing `_phantom`
when using Cacher like so:
fn generate_workout(intensity: u32, random_number: u32) {
let mut cacher = Cacher::new(simulated_expensive_calculation);
// I don't want to pass in _phantom here ^ :(
Am I missing something? Can I tell the compiler to ignore the "missing" type parameter U
, which I'm using in the input to the closure F
?