Найти тему
Ржавый код

Что такое замыкания в Rust

Оглавление

Что такое замыкание?

Замыкание, также известное как анонимная функция или лямбда-выражение, является функцией, определенной в контексте его использования. Они позволяют определять функции в пределах области действия другой функции и могут захватывать переменные из их окружающей области действия.

В Rust замыкания определяются с помощью пары вертикальных черт (`| |`), которые действуют как скобки функции. Между этими символами задаются аргументы функции, за которыми следует блок кода, составляющий тело функции. Рассмотрим основной пример:

-2

Здесь `add_one` является замыканием, которое принимает один аргумент, `x`, и возвращает `x + 1`.

Захват переменных

Сильной особенностью замыканий является их способность захватывать переменные из окружающей среды, обычно называемая upvar capturing. Переменные могут быть зафиксированы тремя способами:

  1. By reference: `&T`
  2. По изменяемой ссылке: `&mut T`
  3. По значению: `Т`

Rust попытается сделать вывод о наименее ограничительном выборе на основе того, как вы используете переменные в замыкании. Давайте продемонстрируем следующее:

-3

В этом примере заимствование захватывает x по ссылке (`&T`), `borrow_mut` захватывает `x` по изменяемой ссылке (`&mut T`) и перемещает захваченную переменную x по значению (`T`). Ключевое слово `move` используется для принудительной передачи в замыкание во владение значения, которые оно использует.

Вывод типа и дженерики

Реализация замыкания в Rust блещет, когда речь заходит о выводе типа и дженериках. В то время как определения функций требуют явных типов для их аргументов, замыкания Rust не требуют. Кроме того, в отличие от функций, замыкания могут быть дженериками для своих типов ввода. Вот пример:

-4

В этом коде `example_closure` можете использовать строку или `i32`, поскольку он является универсальным.

Fn, FnMut, и FnOnce

В Rust мы имеем три трейта для представления трех видов замыканий: `Fn`, `FnMut` и `FnOnce`, которые соответствуют трем способам захвата переменных:

  1. `Fn` принимает переменные по ссылке (`&T`)
  2. `FnMut` принимает переменные по изменяемой ссылке (`&mut T`)
  3. `FnOnce` принимает переменные по значению (`T`)

Каждое замыкание реализует один или несколько из этих трейтов. Если замыкание реализует `Fn`, то оно также реализует `FnMut` и `FnOnce`. Если оно реализует `FnMut`, оно также реализует `FnOnce`.

-5

Практическое использование замыканий

Существует множество способов использования замыканий в Rust для написания краткого и гибкого кода. Давайте обсудим некоторые из них:

В качестве аргументов функций

Функции в Rust могут принимать замыкания в качестве аргументов. Это часто используется в функциях более высокого порядка, которые принимают другие функции в качестве аргументов или возвращают их в качестве результатов.

Вот пример, где мы используем замыкание для реализации функции `map`, подобной функции `map` на итераторах:

-6

В этом примере `map` принимает `i32`, а замыкание в качестве аргументов применяет замыкание к значению и возвращает результат.

Замыкания в структурах данных

Хранение замыкания в структуре для последующего выполнения является типичным шаблоном в Rust, особенно в конструкциях, управляемых событиями или обратными вызовами.

-7

В этом примере создается структура `Button`, хранящая замыкание как обратный вызов. При нажатии кнопки вызывается обратный вызов.

Замыкания с итераторами

Замыкания широко используются с итераторами в Rust. Они обеспечивают краткий способ выполнения операций над каждым элементом сбора. Например:

-8

В этом примере замыкание `| x | x * x` передается методу `map` итератора, который применяет замыкание к каждому элементу.

В заключение

Замыкание Rust - это захватывающая параметры функция, обеспечивающая гибкость и лаконичность кода. Оно гибко захватывают в свою среду, может использоваться аналогично функциям и приносит такие преимущества, как определение охвата видимости и типа. Оно может использоваться в качестве функциональных параметров, храниться в структурах данных для последующего использования и в паре с итераторами для эффективной обработки данных.

Статья на rusty-code.ru