Замыкания - анонимные функции. Их можно присвоить переменным и вызывать. Это также функция, которая ссылается на свободные переменные в своей области видимости. Базовое использование:
letadd_one=|x: i32|-> i32{x+1};println!("Add one to 5 = {}",add_one(5));// Add one to 5 = 6
letadd_two=|x|x+2;println!("Add two to 5 = {}",add_two(5));// Add two to 5 = 7
letadd=|a,b|a+b;println!("Sum of 5 and 6 = {}",add(5,6));// Sum of 5 and 6 = 11
letjust_number=||42;println!("Answer to all: {}",just_number());// Answer to all: 42
В отличие от функций, замыкания могут использовать переменные вне своего блока:
(0..3).for_each(|x|{println!("map i = {}",x*2);});letfactor=2;letmultiplier=|x|x*factor;println!("{}",multiplier(5));// 10
println!("Factor: {factor}");// factor ещё доступен тут
Это нужно для того, чтобы замыкание получило владение данным и пережило scope, в котором оно было объявлено.
Работа с итераторами
.map(<closure>) передаёт владение элементами итератора замыканию, чтобы их можно было трансформировать в другие элементы, которые далее возвращает замыкание.
.filter(<closure>) возвращает оригинальные элементы, когда предикат замыкания возвращает true. Таким образом, отдавать владение элементами замыканию нельзя, и нужно передавать по ссылке.
Можно вернуть элементы, когда предикат значения true, и сразу же их трансформировать. На вход он принимает замыкание, возвращающее Option<T>:
Если на выходе Some(value), значение включается в результат;
Если замыкание возвращает None, элемент исключается фильтром.
letnumbers=vec!["1","2","abc","4"];// Раздельно: filter() и потом map()
letresult: Vec<i32>=numbers.iter().filter(|s|s.parse::<i32>().is_ok())// фильтровать цифры
.map(|s|s.parse::<i32>().unwrap())// Перевести их в int
.collect();// Result: [1, 2, 4]
// Вместе: filter_map()
letresult: Vec<i32>=numbers.iter().filter_map(|s|s.parse::<i32>().ok())// фильтр и перевод в 1 шаг
.collect();// Result: [1, 2, 4]
Вложенные замыкания map()
leta=(0..=3).map(|x|x*2).map(|y|y-1);// первая итерация map(): 2, 4, 6
// вторая итерация map(): 1, 3, 5
foriina{println!("{i}");}
All
Замыкание all возвращает True, если все элементы в замыкании соответствуют условию.
leta: Vec<i32>=vec![1,2,3,4];print!("{}\n",a.into_iter().all(|x|x>1));// false
Для пустого вектора замыкание all вернёт True:
leta: Vec<i32>=vec![];print!("{}\n",a.into_iter().all(|x|x>1));// true
Цикл через замыкание vs for
usestd::collections::HashMap;pubfnmain(){letnum_vec=vec![1,2,1,3,5,2,1,4,6];letmutnumber_count: HashMap<i32,i32>=HashMap::new();forkeyinnum_vec{*number_count.entry(key).or_default()+=1;}/* for (k, v) in number_count {
print!("{} -> {}; ", k, v);
} */number_count.iter().for_each(|(k,v)|{print!("{} -> {}; ",k,v);});//цикл через замыкание итератора
}