Range Over Iterators in Rust
Our first program will demonstrate iterating over various elements using iterators. Here’s how to do it in the target language.
use std::cell::RefCell;
use std::rc::Rc;
struct List<T> {
head: Option<Rc<RefCell<Element<T>>>>,
tail: Option<Rc<RefCell<Element<T>>>>,
}
struct Element<T> {
next: Option<Rc<RefCell<Element<T>>>>,
val: T,
}
impl<T> List<T> {
fn new() -> Self {
List { head: None, tail: None }
}
fn push(&mut self, v: T) {
let new_tail = Rc::new(RefCell::new(Element { next: None, val: v }));
match self.tail.take() {
Some(old_tail) => old_tail.borrow_mut().next = Some(new_tail.clone()),
None => self.head = Some(new_tail.clone())
}
self.tail = Some(new_tail);
}
fn all(&self) -> impl Iterator<Item = T>
where
T: Clone,
{
struct AllIter<T>(Option<Rc<RefCell<Element<T>>>>);
impl<T> Iterator for AllIter<T>
where
T: Clone,
{
type Item = T;
fn next(&mut self) -> Option<T> {
self.0.take().map(|e| {
let el = e.borrow();
self.0 = el.next.clone();
el.val.clone()
})
}
}
AllIter(self.head.clone())
}
}
fn gen_fib() -> impl Iterator<Item = i32> {
struct FibIter(i32, i32);
impl Iterator for FibIter {
type Item = i32;
fn next(&mut self) -> Option<i32> {
let (a, b) = (self.0, self.1);
self.0 = b;
self.1 = a + b;
Some(a)
}
}
FibIter(1, 1)
}
fn main() {
let mut lst = List::new();
lst.push(10);
lst.push(13);
lst.push(23);
for e in lst.all() {
println!("{}", e);
}
let all: Vec<_> = lst.all().collect();
println!("all: {:?}", all);
for n in gen_fib() {
if n >= 10 {
break;
}
println!("{}", n);
}
}
In Rust, we define our List
and Element
structs for a generic type T
. We use RefCell
and Rc
for interior mutability and reference counting, respectively. The push
method adds new elements to the list.
The all
method returns an iterator over the list elements. This iterator is implemented in the AllIter
struct, which uses the Iterator
trait to define the iteration behavior.
We also define a gen_fib
function that returns an iterator over the Fibonacci sequence, using the Iterator
trait to generate new Fibonacci numbers.
In the main
function, we create a list, add elements, and demonstrate iterating over list elements and Fibonacci numbers, using Rust’s collection and iteration features.
This example illustrates how to use Rust’s iterators effectively and how to create custom iterators for complex data structures.