Замыкания и итераторы
Замыкания — анонимные функции, захватывающие окружение; итераторы лениво обрабатывают последовательности.
Замыкание (closure) — анонимная функция, которая может захватывать переменные из окружающего кода.
Замыкания
Замыкание — это функция без имени, которую можно сохранить в переменную или передать другой функции. Параметры записывают между вертикальными чертами |...|.
fn main() {
let add = |a: i32, b: i32| a + b; // замыкание из двух аргументов
let square = |x| x * x; // типы выводятся
println!("{}", add(2, 3));
println!("{}", square(5));
}Вывод:
5 25
Главная особенность — замыкание захватывает переменные из окружения. Обычная функция так не умеет.
fn main() {
let factor = 10;
let multiply = |x| x * factor; // factor захвачен из окружения
println!("{}", multiply(5));
}Вывод:
50
Итераторы
Итератор — это последовательность значений, которую можно обходить. Вызов .iter() на коллекции даёт итератор. Его сила — в цепочках преобразований map, filter и других, которые принимают замыкания.
fn main() {
let nums = vec![1, 2, 3, 4, 5, 6];
// оставить чётные, удвоить, собрать в новый вектор
let result: Vec<i32> = nums
.iter()
.filter(|&&x| x % 2 == 0) // оставляем чётные
.map(|&x| x * 2) // удваиваем
.collect(); // собираем в Vec
println!("{:?}", result);
}Вывод:
[4, 8, 12]
Ленивость итераторов
Важная деталь: map и filter ленивы — сами по себе они ничего не вычисляют, а только описывают, что нужно сделать. Работа происходит только когда цепочку «завершают» методом-потребителем вроде collect, sum или for. Благодаря этому промежуточных коллекций не создаётся, и цепочки остаются быстрыми.
fn main() {
let nums = vec![1, 2, 3, 4, 5];
// сумма квадратов нечётных чисел
let total: i32 = nums
.iter()
.filter(|&&x| x % 2 == 1)
.map(|&x| x * x)
.sum(); // потребитель: запускает всю цепочку
println!("{total}");
}Вывод:
35
(1 + 9 + 25 = 35: квадраты 1, 3 и 5.) Такие цепочки заменяют циклы с ручным накоплением и читаются как описание задачи, а не как пошаговая инструкция.
Часто используемые методы итераторов
| Метод | Что делает |
map(f) | преобразовать каждый элемент |
filter(p) | оставить элементы, удовлетворяющие условию |
collect() | собрать в коллекцию (Vec, HashMap...) |
sum() / count() | сумма / количество элементов |
enumerate() | добавить индекс к каждому элементу |
Итог
- Замыкания — анонимные функции
|args| тело, способные захватывать окружение. - Итераторы с
map/filter/collectвыражают обработку данных декларативно. - Итераторы ленивы: цепочка вычисляется только при вызове метода-потребителя (
collect,sum).