Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling closures from an array in Rust

How do I iterate over an array of closures, calling each one in turn?

With functions, I discovered I could do this by just iterating over the array, and dereferencing the values that produced:

fn square(x: int) -> int { x * x }

fn add_one(x: int) -> int { x + 1 }

fn main() {
    let funcs  = [square, add_one];
    for func in funcs.iter() {
        println!("{}", (*func)(5i));
    }
}

However, when I try to do the same with closures, I get an error:

fn main() {
    let closures = [|x: int| x * x, |x| x + 1];
    for closure in closures.iter() {
        println!("{}", (*closure)(10i));
    }
}

Produces:

<anon>:4:24: 4:34 error: closure invocation in a `&` reference
<anon>:4         println!("{}", (*closure)(10i));
                                ^~~~~~~~~~
note: in expansion of format_args!
<std macros>:2:23: 2:77 note: expansion site
<std macros>:1:1: 3:2 note: in expansion of println!
<anon>:4:9: 4:41 note: expansion site
<anon>:4:24: 4:34 note: closures behind references must be called via `&mut`
<anon>:4         println!("{}", (*closure)(10i));
                                ^~~~~~~~~~
note: in expansion of format_args!
<std macros>:2:23: 2:77 note: expansion site
<std macros>:1:1: 3:2 note: in expansion of println!
<anon>:4:9: 4:41 note: expansion site

If I try declaring the iteration variable ref mut, it still doesn't work:

fn main() {
    let closures = [|x: int| x * x, |x| x + 1];
    for ref mut closure in closures.iter() {
        println!("{}", (*closure)(10i));
    }
}

Results in:

<anon>:4:24: 4:39 error: expected function, found `&|int| -> int`
<anon>:4         println!("{}", (*closure)(10i));
                                ^~~~~~~~~~~~~~~
note: in expansion of format_args!
<std macros>:2:23: 2:77 note: expansion site
<std macros>:1:1: 3:2 note: in expansion of println!
<anon>:4:9: 4:41 note: expansion site

If I add another dereference:

fn main() {
    let closures = [|x: int| x * x, |x| x + 1];
    for ref mut closure in closures.iter() {
        println!("{}", (**closure)(10i));
    }
}

I get back to the original error:

<anon>:4:24: 4:35 error: closure invocation in a `&` reference
<anon>:4         println!("{}", (**closure)(10i));
                                ^~~~~~~~~~~
note: in expansion of format_args!
<std macros>:2:23: 2:77 note: expansion site
<std macros>:1:1: 3:2 note: in expansion of println!
<anon>:4:9: 4:42 note: expansion site
<anon>:4:24: 4:35 note: closures behind references must be called via `&mut`
<anon>:4         println!("{}", (**closure)(10i));
                                ^~~~~~~~~~~
note: in expansion of format_args!
<std macros>:2:23: 2:77 note: expansion site
<std macros>:1:1: 3:2 note: in expansion of println!
<anon>:4:9: 4:42 note: expansion site

What am I missing here? Is there documentation somewhere that describes how this works?

like image 923
Brian Campbell Avatar asked Oct 10 '14 14:10

Brian Campbell


1 Answers

The .iter() method of vector yields immutable references, you need mutable ones to call the closure, thus you should use .iter_mut() :

fn main() {
    let mut closures = [|x: int| x * x, |x| x + 1];
    for closure in closures.iter_mut() {
        println!("{}", (*closure)(10i));
    }
}

-----

100
11
like image 157
Levans Avatar answered Oct 15 '22 13:10

Levans