Closures are function like constructs that you can store in a variable. They are functions without names that we can save inside a variable or pass to other functions.
The term "closure" is used to be explicit about the ability of these functions to capture and manipulate variables from their enclosing scope, which may involve complex ownership and borrowing rules.
assuming giving the following the following of Cities:
struct City {
city: String,
population: u64,
}
let mut vec: Vec<City> = Vec::new();
vec.push(City {
city: String::from("A"),
population: 100,
});
vec.push(City {
city: String::from("B"),
population: 80,
});
vec.push(City {
city: String::from("C"),
population: 70,
});
we can try to sort it in two ways. with closures
fn pop_helper(pop: &City) -> u64 {
pop.population
}
vec.sort_by_key(pop_helper);
vec.sort_by_key(|p| p.population);
another thing note is that closures contains type annotations. which makes it more powerful than python lambdas
, however in general rust closures are similar to python lambdas
. eg:
let add = |x: i32| -> i32 { x + 1 };
// the same thing as:
fn add_one(x: i32) -> i32 {
x + 1
}
let add_v2 = |x| x + 1;
add_v2(5 as i32); // correct
add_v2(7 as i128); // error
Closures are not allocated on the heap
unless placed inside a collection
like vectors
Iterators are a way of processing a series of elements
all iterators implements the following trait:
pub trait Iterator {
type Item;
fn next(&mut self) -> Option<Self::Item>;
/// default methods
}
An iterator is any type that implements the iterator trait. E.g
struct Item {
name: String,
}
let mut vec: Vec<Item> = Vec::new();
vec.push(Item {
name: String::from("water"),
});
vec.push(Item {
name: String::from("shoes"),
});
let itm = vec.into_iter().filter(|i| i.name == product).collect()
println!("{:?}", itm);