0
votes

Very similarly to Iterate over vector of functions, I'd like to iterate over a vec of functions. The difference being, I'd like to call each function and return a object that has the trait std::fmt::Display.

use std::time::Instant;
use std::fmt;

fn timer<T: fmt::Display> (msg: &str, x: &Fn() -> T) -> T {
    let now = Instant::now();
    let val = x();
    println!("({}) took {} ms\n\tResult: {}", 
        msg,
        now.elapsed().subsec_nanos() / 1000,
        val
    );
    val
}

fn run_all<T: fmt::Display> () {
    let problems: Vec<&Fn() -> T> = vec![
        &|| prob_1(1000),
        &|| prob_2(4_000_000),
        &|| prob_3(600_851_475_143),
        &|| prob_4(3),
        &|| prob_5(20),
        &|| prob_6(100),
        &|| prob_7(10_000)
    ];

    for (i, func) in problems.iter().enumerate() {
        let problem_num: &str = ((i as u64) + 55).to_string().as_str();
        timer(i, &func);
    }
}

One of the seven compiler errors cranked out looks like

error[E0308]: mismatched types
  --> euler.rs:17:13
   |
17 |         &|| prob_1(1000),
   |             ^^^^^^^^^^^^ expected type parameter, found u32
   |
   = note: expected type `T`
              found type `u32`

Each of these functions returns a u32 or u64 as of yet (they're Project Euler problems), but I'd like, if possible to have this generalized across all types sharing the trait.

1
You haven't shown us the type signature for any of the prob_X functions, so there is no way to reproduce your issue or answer this.loganfsmyth
@loganfsmyth prob_1 is u32 -> u32, prob_3 is u64 -> u64. The timer function's type works for individual calls with each of the various problem call closures, it's the collection of closures and type checker I seem to be hung up on now.wegry

1 Answers

1
votes

Well first things first, you're going to get lifetime errors with your current setup, so lets switch to using something other than references to closures that immediately go out of scope...

let problems: Vec<fn() -> T> = vec![
        || prob_1(1000),
        || prob_2(4_000_000),
        || prob_3(600_851_475_143),
        || prob_4(3),
        || prob_5(20),
        || prob_6(100),
        || prob_7(10_000)
    ];

Now this error is happening because your functions return a concrete type (namely u32 or u64). These are not implicitly cast to T, you have to do that manually. I suggest looking up the From trait and implementing that so that you can do the conversion. Otherwise, use concrete types everywhere.