computation entirely. This could be done for the example above by adjusting the
`b.iter` call to
-```{rust,ignore}
-# struct X; impl X { fn iter<T>(&self, _: || -> T) {} } let b = X;
+```rust
+# struct X;
+# impl X { fn iter<T, F>(&self, _: F) where F: FnMut() -> T {} } let b = X;
b.iter(|| {
// note lack of `;` (could also use an explicit `return`).
range(0u, 1000).fold(0, |old, new| old ^ new)
is an opaque "black box" to the optimizer and so forces it to consider any
argument as used.
-```{rust,ignore}
+```rust
extern crate test;
# fn main() {
-# struct X; impl X { fn iter<T>(&self, _: || -> T) {} } let b = X;
+# struct X;
+# impl X { fn iter<T, F>(&self, _: F) where F: FnMut() -> T {} } let b = X;
b.iter(|| {
test::black_box(range(0u, 1000).fold(0, |old, new| old ^ new));
});
Let's make a closure:
-```{rust,ignore}
-let add_one = |x| { 1 + x };
+```{rust}
+let add_one = |&: x| { 1 + x };
println!("The sum of 5 plus 1 is {}.", add_one(5));
```
Let's compare syntax. The two are pretty close:
-```{rust,ignore}
-let add_one = |x: i32| -> i32 { 1 + x };
-fn add_one (x: i32) -> i32 { 1 + x }
+```{rust}
+let add_one = |&: x: i32| -> i32 { 1 + x };
+fn add_one (x: i32) -> i32 { 1 + x }
```
As you may have noticed, closures infer their argument and return types, so you
the name: a closure "closes over its environment." What does that mean? It means
this:
-```{rust,ignore}
+```{rust}
fn main() {
- let x = 5;
+ let x: i32 = 5;
- let printer = || { println!("x is: {}", x); };
+ let printer = |&:| { println!("x is: {}", x); };
printer(); // prints "x is: 5"
}
fn main() {
let mut x = 5;
- let printer = || { println!("x is: {}", x); };
+ let printer = |&:| { println!("x is: {}", x); };
x = 6; // error: cannot assign to `x` because it is borrowed
}
Closures are most useful as an argument to another function. Here's an example:
-```{rust,ignore}
-fn twice(x: i32, f: |i32| -> i32) -> i32 {
+```{rust}
+fn twice<F: Fn(i32) -> i32>(x: i32, f: F) -> i32 {
f(x) + f(x)
}
fn main() {
- let square = |x: i32| { x * x };
+ let square = |&: x: i32| { x * x };
twice(5, square); // evaluates to 50
}
Let's break the example down, starting with `main`:
-```{rust,ignore}
-let square = |x: i32| { x * x };
+```{rust}
+let square = |&: x: i32| { x * x };
```
We've seen this before. We make a closure that takes an integer, and returns
its square.
-```{rust,ignore}
-# fn twice(x: i32, f: |i32| -> i32) -> i32 { f(x) + f(x) }
-# let square = |x: i32| { x * x };
+```{rust}
+# fn twice<F: Fn(i32) -> i32>(x: i32, f: F) -> i32 { f(x) + f(x) }
+# let square = |&: x: i32| { x * x };
twice(5, square); // evaluates to 50
```
how the `|i32| -> i32` syntax looks a lot like our definition of `square`
above, if we added the return type in:
-```{rust,ignore}
-let square = |x: i32| -> i32 { x * x };
-// |i32| -> i32
+```{rust}
+let square = |&: x: i32| -> i32 { x * x };
+// |i32| -> i32
```
This function takes an `i32` and returns an `i32`.
Okay, let's look at the body of `twice`:
-```{rust,ignore}
-fn twice(x: i32, f: |i32| -> i32) -> i32 {
+```{rust}
+fn twice<F: Fn(i32) -> i32>(x: i32, f: F) -> i32 {
f(x) + f(x)
}
```
If we didn't want to give `square` a name, we could just define it inline.
This example is the same as the previous one:
-```{rust,ignore}
-fn twice(x: i32, f: |i32| -> i32) -> i32 {
+```{rust}
+fn twice<F: Fn(i32) -> i32>(x: i32, f: F) -> i32 {
f(x) + f(x)
}
A named function's name can be used wherever you'd use a closure. Another
way of writing the previous example:
-```{rust,ignore}
-fn twice(x: i32, f: |i32| -> i32) -> i32 {
+```{rust}
+fn twice<F: Fn(i32) -> i32>(x: i32, f: F) -> i32 {
f(x) + f(x)
}
after the trait name, using the same syntax used in [generic
functions](#generic-functions).
-``` ignore
+```
trait Seq<T> {
fn len(&self) -> uint;
fn elt_at(&self, n: uint) -> T;
- fn iter(&self, |T|);
+ fn iter<F>(&self, F) where F: Fn(T);
}
```
In this example, we define a function `ten_times` that takes a higher-order
function argument, and call it with a lambda expression as an argument.
-``` ignore
-fn ten_times(f: |int|) {
+```
+fn ten_times<F>(f: F) where F: Fn(int) {
let mut i = 0;
while i < 10 {
f(i);
An example of a `fn` type:
-``` ignore
+```
fn add(x: int, y: int) -> int {
return x + y;
}
let mut x = add(5,7);
-type Binop<'a> = |int,int|: 'a -> int;
+type Binop = fn(int, int) -> int;
let bo: Binop = add;
x = bo(5,7);
```
An example of creating and calling a closure:
-``` ignore
+```rust
let captured_var = 10i;
-let closure_no_args = || println!("captured_var={}", captured_var);
+let closure_no_args = |&:| println!("captured_var={}", captured_var);
-let closure_args = |arg: int| -> int {
+let closure_args = |&: arg: int| -> int {
println!("captured_var={}, arg={}", captured_var, arg);
arg // Note lack of semicolon after 'arg'
};
-fn call_closure(c1: ||, c2: |int| -> int) {
+fn call_closure<F: Fn(), G: Fn(int) -> int>(c1: F, c2: G) {
c1();
c2(2);
}