4

I'm following along with the Rust Programming Language https://doc.rust-lang.org/book/ and in Chapter 13 on closures I'm trying to make the example code use generics.

I can make the output value generic as follows:

struct Cacher<T, V> 
    where T: Fn(u32) -> V
{
    calculation: T,
    value: Option<V>,
}

impl <T, V> Cacher<T, V>
    where T: Fn(u32) -> V
{
    fn new(calculation: T) -> Cacher<T, V> {
        Cacher {
            calculation,
            value: None,
        }
    }
}

impl <T> Cacher<T, u32>
    where T: Fn(u32) -> u32
{
    fn value(&mut self, arg: u32) -> u32 {
        match self.value {
            Some(v) => v,
            None => {
                let v = (self.calculation)(arg);
                self.value = Some(v);
                v
            },
        }
    }
}

but when I try to make the input generic:

struct Cacher<T, I, V> 
    where T: Fn(I) -> V
{
    calculation: T,
    value: Option<V>,
}

impl <T, I, V> Cacher<T, I, V>
    where T: Fn(I) -> V
{
    fn new(calculation: T) -> Cacher<T, I, V> {
        Cacher {
            calculation,
            value: None,
        }
    }
}

impl <T> Cacher<T, u32, u32>
    where T: Fn(u32) -> u32
{
    fn value(&mut self, arg: u32) -> u32 {
        match self.value {
            Some(v) => v,
            None => {
                let v = (self.calculation)(arg);
                self.value = Some(v);
                v
            },
        }
    }
}

... I get E0392 parameter 'I' is never used.

I can sort of understand that I is not really part of defining the struct Cacher but I haven't figured out the proper way to tell the compiler that "T is any closure that takes one parameter and returns a V". I've seen some discussions that seem to relate to this, mentioning e.g. PhantomData but I don't quite follow them. Can somebody explain in simple terms? :)

  • 1
    Have you looked at the doc for `PhantomData`, and especially [this paragraph](https://doc.rust-lang.org/stable/std/marker/struct.PhantomData.html#unused-type-parameters)? – Jmb Mar 05 '19 at 10:25
  • Thanks for the pointer @jmb, that does indeed work. I'm still unsure why it's needed, and whether this is the accepted way to do what I'm trying to do. This is after all an example from the Book, so a nice unambiguous answer would be nice if it exists! – Kristoffer Sjöö Mar 05 '19 at 11:52
  • [Specify `Fn` trait bound on struct definition without fixing one of the `Fn` parameters](https://stackoverflow.com/questions/50671177/specify-fn-trait-bound-on-struct-definition-without-fixing-one-of-the-fn-par) may help you. (disclosure: I wrote the accepted answer) – trent Mar 05 '19 at 14:15
  • 1
    Possible duplicate of [Specify \`Fn\` trait bound on struct definition without fixing one of the \`Fn\` parameters](https://stackoverflow.com/questions/50671177/specify-fn-trait-bound-on-struct-definition-without-fixing-one-of-the-fn-par) – trent Mar 05 '19 at 14:38

0 Answers0