Rust provides closures and iterators to enable functional programming. In first look it looks great, like the same nice functional programming in other programming languages, but a deeper check exposes that rust suffers from non friendly requirements. See the following example which demonstrates the weird iterators and closure interactions.
fn main() {
let mut updated_numbers: Vec<i32> = Vec::new();
let numbers = vec![1, 5, 4, 7, 8, 9];
// long and explicit definition of a closure
let decrement_number = |x: &i32| -> i32{
println!("decrement a number");
// here we access a variable from outside the closure scope
updated_numbers.push(x.clone());
x - 1
};
// short hand implicit definition of a closure
let increment_number = |x| x + 1;
// we use iterators to create new vectors
let incremented: Vec<i32> = numbers.iter().map(increment_number).collect();
let back_to_origin: Vec<i32> = incremented.iter().map(decrement_number).collect();
println!("numbers {:?}", numbers);
println!("incremented {:?}", incremented);
println!("and decremented back {:?}", back_to_origin);
println!("we've updated the following {:?}", updated_numbers);
/*
It turns out functional programming in rust is no fun!
iter() - creates a pointer to the items
filter() - creates another pointer to the pointer to the items
hence, we have a double pointer in the filter, very unexpected behavior
*/
let filter_even = |x: &&i32| -> bool { return *x % 2 == 0 };
let even: Vec<i32> = numbers.iter().filter(filter_even).map(|x: &i32| -> i32 { *x }).collect();
/*
This emphasise the complex rust internals.
we must redefine the closures since the order of actions is different
*/
let filter_even = |x: &i32| -> bool { return x % 2 == 0 };
let decrement_number = |x| x -1;
let odd: Vec<i32> = numbers.iter().map(increment_number).filter(filter_even).map(decrement_number).collect();
println!("even numbers are {:?}", even);
println!("odd numbers are {:?}", odd);
}
No comments:
Post a Comment