// Example 8: closures, (bounded) polymorphism fn twice_i32<F>(x0: i32, f: &F) -> i32 where F: Fn(i32) -> i32 { // ^ ^ // closure named `f`, which | | // is a (generic type) `F` where ^~~ | // `F` is an Fn (i.e. closure) that takes an `i32` ^~~ // ... and returns an `i32`. let x1 = f(x0); // (work-around weakness in current borrow-checker) f(x1) } pub fn main() { println!("twice_i32(0, add_1): {}", twice_i32(0, &|y| y+1)); let w = 3; println!("twice_i32(0, add_w): {}", twice_i32(0, &|z| z+w)); println!("twice(0, add_1): {}", twice(0i32, &|y| y+1)); // println!("twice_peano(0): {}", twice_peano(0i32)); // XXX (see exercise below) } pub fn twice<X, F>(x: X, f: &F) -> X where F: Fn(X) -> X { let x1 = f(x); f(x1) } pub trait Peano { fn succ(self) -> Self; } #[cfg(exercise_for_reader)] impl Peano for i32 { } pub fn twice_peano<X:Peano>(x: X) -> X { #![allow(unused_variables)] unimplemented!() // Hint: review ex4.rs } // EXERCISE: finish implementing Peano for `i32`; uncomment line marked XXX above. // EXERCISE: The first two calls to `twice_i32` in `main` illustrate // closures closed over their environment. Try to make the classic // `make_adder` example of a higher-order function, i.e. defined // analogously to `make_adder ≡ λw.λz.z+w` // // Discuss.