Rust - Итератор и закрытие

В этой главе мы узнаем, как работают итераторы и замыкания в RUST.

Итераторы

Итератор помогает перебирать набор значений, таких как массивы, векторы, карты и т. Д. Итераторы реализуют черту Iterator, которая определена в стандартной библиотеке Rust. Метод iter () возвращает объект-итератор коллекции. Значения в объекте итератора называются элементами. Метод next () итератора может использоваться для обхода элементов. Метод next () возвращает значение None, когда достигает конца коллекции.

В следующем примере итератор используется для чтения значений из массива.

fn main() {
   //declare an array
   let a = [10,20,30];

   let mut iter = a.iter(); 
   // fetch an iterator object for the array
   println!("{:?}",iter);

   //fetch individual values from the iterator object
   println!("{:?}",iter.next());
   println!("{:?}",iter.next());
   println!("{:?}",iter.next());
   println!("{:?}",iter.next());
}

Вывод

Iter([10, 20, 30])
Some(10)
Some(20)
Some(30)
None

Если коллекция, такая как array или Vector, реализует черту Iterator, то ее можно пройти, используя синтаксис for ... in, как показано ниже:

fn main() {
   let a = [10,20,30];
   let iter = a.iter();
   for data in iter{
      print!("{}\t",data);
   }
}

Вывод

10 20 30

Следующие 3 метода возвращают объект-итератор из коллекции, где T представляет элементы в коллекции.

Старший Нет Методы и описание
1

iter()

дает итератор над & T (ссылка на T)

2

into_iter()

дает итератор по T

3

iter_mut()

дает итератор над & mut T

Иллюстрация: iter ()

Функция iter () использует концепцию заимствования. Он возвращает ссылку на каждый элемент коллекции, оставляя коллекцию нетронутой и доступной для повторного использования после цикла.

fn main() {
   let names = vec!["Kannan", "Mohtashim", "Kiran"];
   for name in names.iter() {
      match name {
         &"Mohtashim" => println!("There is a rustacean among us!"),
         _ => println!("Hello {}", name),
      }
   }
   println!("{:?}",names); 
   // reusing the collection after iteration
}

Вывод

Hello Kannan
There is a rustacean among us!
Hello Kiran
["Kannan", "Mohtashim", "Kiran"]

Иллюстрация - into_iter ()

Эта функция использует концепцию владения. Он перемещает значения из коллекции в объект iter, т. Е. Коллекция потребляется и больше не доступна для повторного использования.

fn main(){
   let names = vec!["Kannan", "Mohtashim", "Kiran"];
   for name in names.into_iter() {
      match name {
         "Mohtashim" => println!("There is a rustacean among us!"),
         _ => println!("Hello {}", name),
      }
   }
   // cannot reuse the collection after iteration
   //println!("{:?}",names); 
   //Error:Cannot access after ownership move
}

Вывод

Hello Kannan
There is a rustacean among us!
Hello Kiran

Иллюстрация - for и iter_mut ()

Эта функция похожа на функцию iter () . Однако эта функция может изменять элементы в коллекции.

fn main() {
   let mut names = vec!["Kannan", "Mohtashim", "Kiran"];
   for name in names.iter_mut() {
      match name {
         &mut "Mohtashim" => println!("There is a rustacean among us!"),
         _ => println!("Hello {}", name),
      }
   }
   println!("{:?}",names);
   //// reusing the collection after iteration
}

Вывод

Hello Kannan
There is a rustacean among us!
Hello Kiran
["Kannan", "Mohtashim", "Kiran"]

Закрытие

Замыкание относится к функции внутри другой функции. Это анонимные функции - функции без имени. Замыкание можно использовать для присвоения функции переменной. Это позволяет программе передавать функцию в качестве параметра другим функциям. Замыкание также известно как встроенная функция. Переменные во внешней функции могут быть доступны встроенным функциям.

Синтаксис: определение замыкания

Определение замыкания может дополнительно иметь параметры. Параметры заключены в две вертикальные полосы.

let closure_function = |parameter| {
   //logic
}

Синтаксис вызова Closure реализует Fnчерты. Итак, его можно вызвать с помощью() синтаксис.

closure_function(parameter);    //invoking

Иллюстрация

В следующем примере определяется замыкание is_even в функции main () . Замыкание возвращает истину, если число четное, и ложь, если число нечетное.

fn main(){
   let is_even = |x| {
      x%2==0
   };
   let no = 13;
   println!("{} is even ? {}",no,is_even(no));
}

Вывод

13 is even ? false

Иллюстрация

fn main(){
   let val = 10; 
   // declared outside
   let closure2 = |x| {
      x + val //inner function accessing outer fn variable
   };
   println!("{}",closure2(2));
}

Функция main () объявляет переменную val и закрытие. Замыкание обращается к переменной, объявленной во внешней функции main () .

Вывод

12