Mismatched types when creating dispatch table

I was trying to create an example for dispatch tables. the first way, with a temporary mutable and calling insert works, but when I try to create table2 I get mismatched types error with some further details:

^ expected `HashMap<char, fn(i32, i32) -> i32>`, found `HashMap<char, fn(i32, i32) -> i32 {add}>`

Why is the difference?

use std::collections::HashMap;

fn add(x: i32, y: i32) -> i32 {
    x + y
}

fn multiply(x: i32, y: i32) -> i32 {
    x * y
}

fn main() {
    let table = {
        let mut table: HashMap<char, fn(i32, i32) -> i32> = HashMap::new();
        table.insert('+', add);
        table.insert('*', multiply);
        table.insert('-', |x, y| x - y);
        table.insert('/', |x, y| x / y);
        table
    };

    let table2: HashMap<char, fn(i32, i32) -> i32> = HashMap::from([
        ('+', add),
        ('*', multiply),
        ('-', |x, y| x - y),
        ('/', |x, y| x / y),
    ]);

    for op in ['+', '*', '-', '/'] {
        let res = table[&op](8, 2);
        println!("8 {op} 2 = {res}");
    }
}

every function that has defined has its own sepcific type (e.g add has fn(i32,i32) -> i32 {add} ),multiply has it as well,I think you can use add as fn(i32,i32) -> i32 to solve this problem.

Thanks.

Indeed the following works, but I'd still like to understand why the first one with the insert worked and this needed this extra hint?

    let table2: HashMap<char, fn(i32, i32) -> i32> = HashMap::from([
        ('+', add as fn(i32, i32) -> i32),
        ('*', multiply),
        ('-', |x, y| x - y),
        ('/', |x, y| x / y),
    ]);

There's a type inference variable between the annotation and the trait parameter, so it isn't coercing the function items and closures in your tuples. This works (not saying it's good).

    let table2: HashMap<_, _> = <[(char, fn(i32, i32) -> i32); 4]>::into([
        ('+', add),
        ('*', multiply),
        ('-', |x, y| x - y),
        ('/', |x, y| x / y),
    ]);

To explain what I meant better, perhaps, this doesn't work:

    // Type inference variable                               v
    let table2 = <HashMap<char, fn(i32, i32) -> i32> as From<_>>::from([
        ('+', add),
        ('*', multiply),
        ('-', |x, y| x - y),
        ('/', |x, y| x / y),
    ]);
1 Like

Briefly explain, the stdlib done the work for you.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.