Editor's note: This question was asked before Rust 1.0 and some of the syntax has changed since then, but the underlying concepts remain. Some answers have been updated for Rust 1.0 syntax.
I'm new to Rust and trying to do something with closures which is trivial in JavaScript, Python, etc. but I am running into lifetime issues in Rust. I understand the error message, but it leads me to believe what I want to do is pretty hard in Rust.
I just want to create an array of functions, a
, such that
a[0]
is the function returning 0a[1]
is the function returning 1a[9]
is the function returning 9I tried:
fn main() {
let a : [||->uint, ..10];
for i in range(0u, 10) {
a[i] = ||{i};
}
println!("{} {} {}", a[1](), a[5](), a[9]())
}
But I got a lifetime error. The reported error was "cannot infer an appropriate lifetime due to conflicting requirements" for the functions in a
because the lifetimes cannot outlive the while
block so that the closures cannot outlive their stack frame, which of course they would because I am invoking them in println!
.
I'm sure there must be a way to build up this array of functions, but how?
You need to use move || i
.
move
implies that this closure will take i
by value rather than by reference. By default, these closures would only take references to i
. In your case it is forbidden as the lifetime of i
is limited to the body of the loop.
Also, Rust will complain that your array may not be fully initialized. To avoid it, you can either use a Vec<_>
, or use std::mem::uninitialized
:
fn main() {
let mut a: [_; 10] = unsafe { std::mem::uninitialized() };
for i in 0..10 {
a[i] = move || i;
}
println!("{} {} {}", a[1](), a[5](), a[9]())
}
It is possible to collect
multiple closures from an iterator into a Vec
:
fn main() {
let a: Vec<_> = (0..10).map(|i| move || i).collect();
println!("{} {} {}", a[1](), a[5](), a[9]());
}
The move
keyword causes ownership of i
to be transferred to the closure.
See also:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With