English 中文(简体)
Rust - Iterator and Closure
  • 时间:2024-11-03

Rust - Iterator and Closure


Previous Page Next Page  

In this chapter, we will learn how iterators and closures work in RUST.

Iterators

An iterator helps to iterate over a collection of values such as arrays, vectors, maps, etc. Iterators implement the Iterator trait that is defined in the Rust standard pbrary. The iter() method returns an iterator object of the collection. Values in an iterator object are called items. The next() method of the iterator can be used to traverse through the items. The next() method returns a value None when it reaches the end of the collection.

The following example uses an iterator to read values from an array.

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 inspanidual values from the iterator object
   println!("{:?}",iter.next());
   println!("{:?}",iter.next());
   println!("{:?}",iter.next());
   println!("{:?}",iter.next());
}

Output

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

If a collection pke array or Vector implements Iterator trait then it can be traversed using the for...in syntax as shown below-

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

Output

10 20 30

The following 3 methods return an iterator object from a collection, where T represents the elements in a collection.

Sr.No Methods & Description
1

iter()

gives an iterator over &T(reference to T)

2

into_iter()

gives an iterator over T

3

iter_mut()

gives an iterator over &mut T

Illustration:iter()

The iter() function uses the concept of borrowing. It returns a reference to each element of the collection, leaving the collection untouched and available for reuse after the loop.

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
}

Output

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

Illustration - into_iter()

This function uses the concept of ownership. It moves values in the collection into an iter object, i.e., the collection is consumed and it is no longer available for reuse.

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
}

Output

Hello Kannan
There is a rustacean among us!
Hello Kiran

Illustration - for and iter_mut()

This function is pke the iter() function. However, this function can modify elements within the collection.

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
}

Output

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

Closure

Closure refers to a function within another function. These are anonymous functions – functions without a name. Closure can be used to assign a function to a variable. This allows a program to pass a function as a parameter to other functions. Closure is also known as an inpne function. Variables in the outer function can be accessed by inpne functions.

Syntax: Defining a Closure

A closure definition may optionally have parameters. Parameters are enclosed within two vertical bars.

let closure_function = |parameter| {
   //logic
}

The syntax invoking a Closure implements Fn traits. So, it can be invoked with () syntax.

closure_function(parameter);    //invoking

Illustration

The following example defines a closure is_even within the function main(). The closure returns true if a number is even and returns false if the number is odd.

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

Output

13 is even ? false

Illustration

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

The main() function declares a variable val and a closure. The closure accesses the variable declared in the outer function main().

Output

12
Advertisements