In this chapter, we will learn how iterators and closures work in RUST.
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 library. 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 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
If a collection like 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!("{}\t",data); } }
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 |
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 }
Hello Kannan There is a rustacean among us! Hello Kiran ["Kannan", "Mohtashim", "Kiran"]
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 }
Hello Kannan There is a rustacean among us! Hello Kiran
This function is like 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 }
Hello Kannan There is a rustacean among us! Hello Kiran ["Kannan", "Mohtashim", "Kiran"]
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 inline function. Variables in the outer function can be accessed by inline functions.
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
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)); }
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)); }
The main() function declares a variable val and a closure. The closure accesses the variable declared in the outer function main().
12