Macro iterate::iterate[][src]

iterate!() { /* proc-macro */ }
Expand description

Create an iterator on the fly

The iterate macro creates an iterator on the fly:

use iterate::iterate;

let mut iterator = iterate![1, 2, 3];
assert_eq!(iterator.next(), Some(1));
assert_eq!(iterator.next(), Some(2));
assert_eq!(iterator.next(), Some(3));
assert_eq!(iterator.next(), None);

The iterator lazily evaluates each of its arguments, one at a time:

use std::cell::Cell;
use iterate::iterate;

let cell = Cell::new(0);
let cell = &cell;

let mut iterator = iterate![
    {cell.set(cell.get() + 1); 1},
    {cell.set(cell.get() + 1); 2},
    {cell.set(cell.get() + 1); 3},
];

assert_eq!(cell.get(), 0);
assert_eq!(iterator.next(), Some(1));

assert_eq!(cell.get(), 1);
assert_eq!(iterator.next(), Some(2));

assert_eq!(cell.get(), 2);
assert_eq!(iterator.next(), Some(3));

assert_eq!(cell.get(), 3);
assert_eq!(iterator.next(), None);

Most usefully, iterate can capture any other IntoIterator type and iterate over it, by prefixing the value with ..:

use iterate::iterate;

let range = 0..5;
let vec = vec![4, 1, 2, 3];

// Iterate captures its arguments by move, and evaluates them lazily, so we
// need to ensure that the vec is captured by reference
let vec = &vec;

let iterator = iterate![
    1,
    ..range,
    ..vec.iter().copied(),
    10
];

let result: Vec<i32> = iterator.collect();
assert_eq!(result, [
    1,
    0, 1, 2, 3, 4,
    4, 1, 2, 3,
    10,
])

Eager and Lazy evaluation

iterate tries to be smart about when it evaluates its arguments eagerly vs lazily. In general it tries to evaluate them lazily, but in cases where it’s sure there will be no side effects, it evaluates ..iter arguments eagerly. It does this so that it can provide a more reliable size_hint.