Rust — концепция захвата переменных с помощью замыкателей

Опубликовано: 16 Февраля, 2023

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

При захвате переменных Rust использует для этого следующие методы:

  • по ссылке: (&T)
  • по значению: Т
  • по изменяемой ссылке: (&mut T)

Пример 1:

Rust




// Rust code by reference
fn main() {
      
    let var = String::from("GeeksforGeeks");
    let name = || println!("`Name`: {}", var);
    name(); //calling the closure
    }

Выход:

Объяснение:

В этом примере замыкание используется для вывода значения, которое заимствует (`&`) 'var' , и сохраняет заимствование и замыкание в переменной 'name' . Это останется там до тех пор, пока ' name' не будет использовано ранее. Как мы знаем, println! требует только аргументов, которые ссылаются на неизменяемые, поэтому ограничений нет. Имя закрытия вызывается с использованием заимствования.

Пример 2:

Rust




// Rust code for by value T
fn main() {
   
    let mut count = 0;
    let mut i= 0;
     
    let mut count_closure = || {
        count += 10;
        println!("`count:{}, value: {}`", i, count);
        i+=1;
    };
 // Calling the closure "count_closure" using a mutable borrow.
    count_closure();
    count_closure();
    count_closure();
    }

Выход:

Объяснение:

В этом примере мы использовали замыкание count_closure, которое может принимать либо изменяемый инкремент счетчика, либо переменную-счетчик (неизменяемую). Мы использовали mut, так как вызов нашего замыкания мутирует с замыканием, для которого требуется выходной параметр. Здесь мы объявили I, который хранит количество вызовов замыкания и соответственно увеличивается.

Пример 3:

Rust




// Rust code for by mutable reference: (&mut T)
fn main() {
 use std::mem;
       
    let moving_variable = Box::new(5);
    let variable_used = || {
        println!("`movable variable value`: {:?}", moving_variable);
        mem::drop(moving_variable);
    };
    variable_used();
}

Выход:

Объяснение:

В этом примере мы импортировали трейт std::mem , который помогает нам управлять памятью после разыменования переменной. Мы создали переменную с именем moving_variable и выделили память в куче со значением 5. Поскольку mem::drop требует типажа (T), поэтому она принимает значение. Переменная типа копирования будет копироваться в замыкание, не затрагивая исходное замыкание. variable_used использует переменную только один раз, поэтому она вызывается только один раз.