title: How do I create a closure that takes either u32 or &str and returns u32 or usize respectively?
body: <p>This is from chapter 13.1 of the Rust book, where we use closures, memoization and generic types. In this example I can already pass two different closures to the struct (<code>Cacher</code>) and get the values accordingly, but they have two be two different instances of the struct in order to handle the types correctly.</p>
  <p>Can I build a generic type so the same instance of the struct can handle receiving either type and give me the value accordingly? Either the same <code>u32</code> I passed, or the length of the <code>&amp;str</code> I passed.</p>
  <pre class="lang-rust prettyprint-override"><code>use std::collections::HashMap;
  use std::thread;
  use std::time::Duration;
  
  fn main() {
      let simulated_user_specified_value = 10;
      let simulated_random_number = 7;
  
      generate_workout(simulated_user_specified_value, simulated_random_number);
  }
  
  fn generate_workout(intensity: u32, random_number: u32) {
      let mut expensive_result = Cacher::new(|num| {
          println!(&quot;calculating slowly...&quot;);
          thread::sleep(Duration::from_secs(2));
          num
      });
  
      if intensity &lt; 25 {
          println!(&quot;Today, do {} pushups!&quot;, expensive_result.value(intensity));
          println!(&quot;Next, do {} situps!&quot;, expensive_result.value(intensity));
      } else {
          if random_number == 3 {
              println!(&quot;Take a break today! Remember to stay hydrated!&quot;);
          } else {
              println!(
                  &quot;Today, run for {} minutes!&quot;,
                  expensive_result.value(intensity)
              );
          }
      }
  }
  
  struct Cacher&lt;T, U, V&gt;
  where
      T: Fn(U) -&gt; V,
  {
      calculation: T,
      values: HashMap&lt;U, Option&lt;V&gt;&gt;,
  }
  
  impl&lt;T, U, V&gt; Cacher&lt;T, U, V&gt;
  // Generic T is the function where U and V are the parameter and return value respectively for said function.
  where
      T: Fn(U) -&gt; V,
      U: std::cmp::Eq // U must have 3 trait bounds, Eq, Hash, and Copy.
          + std::hash::Hash
          + Copy,
      V: Copy, // V must have trait bound Copy.
  {
      fn new(calculation: T) -&gt; Cacher&lt;T, U, V&gt; {
          Cacher {
              calculation,
              values: HashMap::new(),
          }
      }
  
      fn value(&amp;mut self, arg: U) -&gt; V {
          match self.values.get(&amp;arg) {
              // Get the value for the key in the hashmap.
              Some(v) =&gt; v.unwrap(), // get the value in the option stored in the hashmap.
              None =&gt; {
                  let v = (self.calculation)(arg);
                  self.values.insert(arg, Some(v)); // Put the key/value pair into the hashmap.
                  v
              }
          }
      }
  }
  
  #[cfg(test)]
  mod tests {
      use super::Cacher;
      #[test]
      fn call_with_different_values() {
          let mut c = Cacher::new(|a| a);
  
          let _v1 = c.value(1);
          let v2 = c.value(2);
  
          assert_eq!(v2, 2);
      }
  
      #[test]
      fn call_with_string_usize() {
          let mut c = Cacher::new(|a: &amp;str| a.len());
  
          let v1 = c.value(&quot;Three&quot;);
  
          assert_eq!(v1, 5);
      }
  }
  </code></pre>
  <p>I tried building structs for the <code>value</code> field of the struct and then implementing a trait of that would group them:</p>
  <pre class="lang-rust prettyprint-override"><code>struct CStr&lt;'a&gt; {
      value: &amp;'a str,
  }
  
  struct CInt {
      value: u32,
  }
  
  trait CValue {
      fn get&lt;W: Copy + Eq&gt;(&amp;self) -&gt; W;
  }
  
  impl&lt;'a&gt; CValue for CStr&lt;'a&gt; {
      fn get&lt;W: Copy + Eq&gt;(&amp;self) -&gt; W {
          self.value.len()
      }
  }
  </code></pre>
  <p>So this test would pass</p>
  <pre class="lang-rust prettyprint-override"><code>#[test]
  fn call_with_different_values() {
      let mut c = Cacher::new(|a| a.get());
  
      let v1 = c.value(1);
      let v2 = c.value(&quot;two&quot;);
  
      assert_eq!(v2, 3);
  }
  </code></pre>
  <p>but I am stuck here:</p>
  <pre><code>impl&lt;'a&gt; CValue for CStr&lt;'a&gt; {
      fn get&lt;W: Copy + Eq&gt;(&amp;self) -&gt; W {
          self.value.len() // here
      }
  }
  </code></pre>
  <p>with the error:</p>
  <pre class="lang-none prettyprint-override"><code>[rustc E0308] [E] mismatched types expected type parameter `W` found type `usize`
  </code></pre>