struct Coroutine<YieldT, RecvT = ()> { ... }
Coroutine object
Coroutine object is a reference to a running coroutine, which receives values of type RecvT
and
yields values of type YieldT
. It is used to control the execution of the coroutine and to pass
values to and from it.
A special case of coroutine is a generator (RecvT
is not provided, defaults to ()
), which does
not receive any values, but only yields values. Generators also implement the Iterator trait,
allowing them to be used in for loops.
Example
fn* coroutine() -> Coroutine<i32, i32> {
for i in 0..3 {
let val = yield i;
println!("[in] got {}", val);
}
}
let gen = coroutine();
for i in 0..3 {
let val = gen.send(i);
println!("[out] got {}", val.unwrap());
}
// Output:
// [in] got 0
// [out] got 0
// [in] got 1
// [out] got 1
// [in] got 2
// [out] got 2
Run this example
Methods
impl Coroutine<YieldT, RecvT> { ... }
-
fn cancel(self: &mut Coroutine<YieldT, RecvT>)
Cancels the coroutine
This method can be used to gracefully stop the coroutine early, allowing any
defer
statements in it to run. If the coroutine already ran to completion, this method has no effect.It is still necessary to call free to free the coroutine's resources after it has been closed.
See close for an example of usage.
-
Returns
true
if the coroutine has completed.Example
fn* gen() -> Coroutine<()> { } let gen = gen(); defer gen.free(); assert!(!gen.is_complete()); // Coroutines start in a suspended state. gen.next(); assert!(gen.is_complete());
Run this example -
Sends a value to the coroutine and resumes its execution.
This method can be used to send a value to the coroutine and resume its execution. The coroutine will continue executing from the point where it last yielded, or from the beginning if it has not been started yet.
If the coroutine runs to completion after the value is sent, this method will return
Option::none()
. If the coroutine yields a value, this method will returnOption::some(value)
. -
fn close(self: &mut Coroutine<YieldT, RecvT>)
Cancels the coroutine and frees its resources.
Cancels the coroutine, allowing any
defer
statements in it to run, and frees the coroutine's resources.Example
use std::fs::{Path, File}; use std::string::starts_with; use std::io::{BufferedReader, lines as io_lines}; fn* read_lines(path: Path) -> Coroutine<&[u8]> { let file = File::open(path).unwrap(); defer file.close(); let reader = BufferedReader::new(&file, 1024 * 64); defer reader.free(); let lines = reader.io_lines(); defer lines.free(); for line in lines { yield line.unwrap(); } } let lines = read_lines(Path::new("/proc/stat")); defer lines.close(); for line in lines { // All resources will be freed, even if we break out early. if !line.starts_with("cpu") { break; } println!("{}", line); }
Run this example -
fn free(self: &mut Coroutine<YieldT, RecvT>)
Frees the memory backing the object.
impl Coroutine<T> { ... }
-
Returns the next item, if any.
If the iterator has reached the end, it returns
Option::none()
.See Iterator for more information.
Mixins
impl Coroutine<T> { ... }
-
-
mixin IteratorExt<Coroutine<T>, T>
-
fn fuse(self: &mut Self) -> FusedIterator<Self, T>
Return an iterator that returns
Option::none()
forever after the first one is returned.Iterators can validly reset back to returning values after they are exhausted. This method "caps it off" after they are first exhausted.
-
fn chain<Other>(self: &mut Self, other: &mut Other) -> ChainIterator<Self, Other, T>
Other: Iterator<Other, T>Returns an iterator that yields all elements of
self
and then all elements ofother
.Example
let range = (0..2).chain(&(10..12)); assert_eq!(range.size_hint(), Option::some(4usize)); assert_eq!(range.next(), Option::some(0)); assert_eq!(range.next(), Option::some(1)); assert_eq!(range.next(), Option::some(10)); assert_eq!(range.next(), Option::some(11)); assert_eq!(range.next(), Option::none());
Run this example -
fn merge_sorted<Other>(self: &mut Self, other: &mut Other) -> MergeIterator<Self, Other, T>
Other: Iterator<Other, T>Returns an iterator that merges two sorted iterators into one sorted iterator.
T
must implement Comparable. If the two iterators are not sorted, the resulting order is unspecified.The merge is stable, meaning that the order of equal elements is preserved, with the elements from
self
coming before the elements fromother
(and vice-versa if the iterator is reversed/used with next_back).Example
let range = [0, 2, 4].iter().merge_sorted(&[1, 3].iter()); assert_eq!(range.size_hint(), Option::some(5usize)); assert_eq!(range.next(), Option::some(0)); assert_eq!(range.next(), Option::some(1)); assert_eq!(range.next(), Option::some(2)); assert_eq!(range.next(), Option::some(3)); assert_eq!(range.next(), Option::some(4)); assert_eq!(range.next(), Option::none());
Run this example -
fn skip(self: &mut Self, n: usize) -> SkipIterator<Self, T>
Returns an iterator that skips first
n
values.If the underlying iterator yields fewer than or exactly
n
values, then the iterator will yield no values.Example
let range = (0..5).skip(2); assert_eq!(range.size_hint(), Option::some(3usize)); assert_eq!(range.next(), Option::some(2)); assert_eq!(range.next(), Option::some(3)); assert_eq!(range.next(), Option::some(4)); assert_eq!(range.next(), Option::none());
Run this example -
fn step_by(self: &mut Self, n: usize) -> StepByIterator<Self, T>
Returns an iterator that steps by
n
values.First value will always be yielded, then every
n
-th value.Example
let range = (0..5).step_by(2); assert_eq!(range.size_hint(), Option::some(3usize)); assert_eq!(range.next(), Option::some(0)); assert_eq!(range.next(), Option::some(2)); assert_eq!(range.next(), Option::some(4)); assert_eq!(range.next(), Option::none());
Run this example -
fn take(self: &mut Self, n: usize) -> TakeIterator<Self, T>
Returns an iterator that yields at most
n
elements.Example
let range = (0..5).take(2); assert_eq!(range.size_hint(), Option::some(2usize)); assert_eq!(range.next(), Option::some(0)); assert_eq!(range.next(), Option::some(1)); assert_eq!(range.next(), Option::none());
Run this example -
fn enumerate(self: &mut Self) -> EnumerateIterator<Self, T>
Returns an iterator that attaches a sequence number of each item.
Example
let range = (10..15).enumerate(); assert_eq!(range.size_hint(), Option::some(5usize)); assert_eq!(range.next(), Option::some((0usize, 10))); assert_eq!(range.next(), Option::some((1usize, 11))); assert_eq!(range.next(), Option::some((2usize, 12))); assert_eq!(range.next(), Option::some((3usize, 13))); assert_eq!(range.next(), Option::some((4usize, 14))); assert_eq!(range.next(), Option::none());
Run this example -
Returns the last value of the iterator.
This method always exhausts the iterator. For iterators that implement DoubleEndedIterator, it may be more efficient to use next_back.
Example
let last = (0..5).last(); assert_eq!(last, Option::some(4));
Run this example -
Returns the
n
-th value of the iterator.Example
let nth = (10..100).nth(2); assert_eq!(nth, Option::some(12));
Run this example -
Counts the number of elements in this iterator.
Example
let count = (100..105).count(); assert_eq!(count, 5);
Run this example -
fn inspect<F>(it: &mut Self, func: F) -> InspectIterator<Self, F, T>
F: Fn(T)Inspects each element of the iterator.
Presented chain of iterator combinators, inspect can be used to execute a callback on every element of an iterator. This is useful for debugging.
The elements are passed through unmodified.
Example
let last = (0..3) .iter() .inspect(|i: i32| { println!("I see {}", i) }) .last(); println!("Last: {}", last); // Prints: // I see 0 // I see 1 // I see 2 // Last: 2
Run this example -
fn take_while<F>(iter: &mut Self, fun: F) -> TakeWhileIterator<Self, F, T>
F: Fn(T) -> boolReturns an iterator that yields the elements while a predicate is true.
Example
let range = (0..5).take_while(|x: i32| -> bool { x < 3 }); assert_eq!(range.size_hint(), Option::none()); assert_eq!(range.next(), Option::some(0)); assert_eq!(range.next(), Option::some(1)); assert_eq!(range.next(), Option::some(2)); assert_eq!(range.next(), Option::none());
Run this example -
fn skip_while<F>(iter: &mut Self, fun: F) -> SkipWhileIterator<Self, F, T>
F: Fn(T) -> boolReturns an iterator that skips the elements while a predicate is true.
Example
let range = (0..5).skip_while(|x: i32| -> bool { x < 3 }); assert_eq!(range.size_hint(), Option::none()); assert_eq!(range.next(), Option::some(3)); assert_eq!(range.next(), Option::some(4)); assert_eq!(range.next(), Option::none());
Run this example -
fn map<U, F>(iter: &mut Self, fun: F) -> MapIterator<Self, F, T, U>
F: Fn(T) -> UReturns an iterator that transforms the elements of this iterator.
Example
let range = (0..5).map(|x: i32| -> i32 { x * 2 }); assert_eq!(range.size_hint(), Option::some(5usize)); assert_eq!(range.next(), Option::some(0)); assert_eq!(range.next(), Option::some(2)); assert_eq!(range.next(), Option::some(4)); assert_eq!(range.next(), Option::some(6)); assert_eq!(range.next(), Option::some(8)); assert_eq!(range.next(), Option::none());
Run this example -
fn foreach<F>(iter: &mut Self, fun: F)
F: Fn(T)Executes a function on each element of this iterator.
For readability, it is usually better to use the
for
loop, butforeach
can be useful in cases where a function allocates memory which can be then freed using adefer
expression.Example
use std::fmt::format; (0..5) .iter() .foreach(|x: i32| { let f = format!("{}", x).unwrap(); defer f.free(); println!("{}", f[..]); });
Run this example -
fn filter<F>(iter: &mut Self, fun: F) -> FilterIterator<Self, F, T>
F: Fn(T) -> boolReturns an iterator that yields the elements of this iterator that match a predicate.
Example
let range = (0..5).filter(|x: i32| -> bool { x % 2 == 0 }); assert_eq!(range.size_hint(), Option::none()); assert_eq!(range.next(), Option::some(0)); assert_eq!(range.next(), Option::some(2)); assert_eq!(range.next(), Option::some(4)); assert_eq!(range.next(), Option::none());
Run this example -
Returns the first item matching the predicate.
If there is no item matching the predicate, returns none.
Example
let a = (1..10).find(|x: i32| -> bool { x * x >= 50 }); let b = (1..10).find(|x: i32| -> bool { x * x >= 1000 }); assert_eq!(a, Option::some(8)); assert_eq!(b, Option::none());
Run this example -
Returns the index of the first item matching the predicate.
If there is no item matching the predicate, returns none.
Example
let arr = [1, 2, 3, 1337, 5, 6]; let idx = arr .iter() .find_index(|x: i32| -> bool { x > 100 }) .unwrap(); println!("First number larger than 100: {}", arr[idx]);
Run this example -
fn filter_map<U, F>(iter: &mut Self, fun: F) -> FilterMapIterator<Self, F, T, U>
F: Fn(T) -> Option<U>Transforms and filters the iterator at the same time.
Function
f
is called on each element of this iterator. If it returnsOption::some(...)
, that element is yielded. If it returnsOption::none()
, the element is skipped.Example
let range = (0..6) .iter() .filter_map(|x: i32| -> Option<i32> { if x % 2 == 1 { Option::some(x * 100) } else { Option::none() } }); assert_eq!(range.next(), Option::some(100)); assert_eq!(range.next(), Option::some(300)); assert_eq!(range.next(), Option::some(500));
Run this example -
fn chunks(self: &mut Self, chunk_size: usize) -> ChunksIterator<Self, T>
Returns an iterator of chunks of size
chunk_size
.If the iterator is not divisible by
chunk_size
, the last chunk will be smaller. Panics ifchunk_size
is 0.Example
// Prints: // [ 0 1 2 ] // [ 3 4 5 ] // [ 6 ] for chunk in (0..7).chunks(3) { print!("[ "); for v in chunk { print!("{} ", v); } println!("]"); }
Run this example -
fn reduce<U, F>(iter: &mut Self, initial: U, func: F) -> U
F: Fn(U, T) -> UReduces the iterator into a single value.
Equivalent to:
let value = initial; for element in iter { value = func(value, element); }
Example
let sum = (0..5) .iter() .reduce(0, |acc: i32, x: i32| -> i32 { acc + x }); println!("{}", sum); // Prints: 10
Run this example -
fn sum(iter: &mut Self) -> T
Sums all the values in the iterator.
T
must satisfy Numeric protocol.Example
let sum = (0..5).sum(); assert_eq!(sum, 10);
Run this example -
Returns the minimum value of the iterator.
T
must satisfy Comparable protocol.Example
let min = [1, -5, 10, 200].iter().min(); assert_eq!(min, Option::some(-5));
Run this example -
Returns the maximum value of the iterator.
T
must satisfy Comparable protocol.Example
let max = [1, -5, 10, 200].iter().max(); assert_eq!(max, Option::some(200));
Run this example -
Returns
true
if all elements of the iterator match a predicate,false
otherwise.If iterator produces no values,
true
is returned.Example
let t1 = [1, -5, 10, 200].iter().all(|x: i32| -> bool { x > 0 }); let t2 = [1, -5, 10, 200].iter().all(|x: i32| -> bool { x < 1000 }); assert!(!t1); assert!(t2);
Run this example -
Returns
true
if any element of the iterator matches a predicate,false
otherwise.If iterator produces no values,
false
is returned.Example
let t1 = [1, -5, 10, 200].iter().any(|x: i32| -> bool { x > 1000 }); let t2 = [1, -5, 10, 200].iter().any(|x: i32| -> bool { x < 0 }); assert!(!t1); assert!(t2);
Run this example -
Collects the values of the iterator into a vector.
Example
let range = (0..5).to_vector(); defer range.free(); assert_eq!(range.len(), 5); assert_eq!(range[..], &[0, 1, 2, 3, 4]);
Run this example -
Fills the slice with the values of the iterator.
If the number of elements in the iterator is greater than the length of the slice, the remaining values in the iterator are not consumed.
If the number of elements in the iterator is less than the length of the slice, the remainder of the slice is untouched.
Example
let buf: [i32; 5]; (0..5).fill_slice(buf[..]); assert_eq!(buf[..], &[0, 1, 2, 3, 4]);
Run this example -
fn peekable(self: &mut Self) -> PeekableIterator<Self, T>
-
fn group_by<F, K>(self: &mut Self, func: F) -> GroupByIterator<Self, F, T, K>
F: Fn(T) -> KK: Equatable<K>Returns an iterator of groups grouped by a key.
Requires that the items of the iterator that have the same key are contiguous (e.g. the values are sorted by key).
Example
fn divide_by_three(x: i32) -> i32 { x / 3 } for group in (0..10).group_by(divide_by_three) { print!("{}:", group.key); for value in group { print!(" {}", value); } println!(""); } // Prints: // 0: 0 1 2 // 1: 3 4 5 // 2: 6 7 8 // 3: 9
Run this example -
fn zip<Other>(self: &mut Self, other: &mut Other) -> ZipIterator<Self, Other, T, iterator_yield_t<Other>>
Combines two iterators, returning an iterator of pairs.
Example
let iter = (0..5).zip(&(10..15)); assert_eq!(iter.size_hint(), Option::some(5usize)); assert_eq!(iter.next(), Option::some((0, 10))); assert_eq!(iter.next(), Option::some((1, 11))); assert_eq!(iter.next(), Option::some((2, 12))); assert_eq!(iter.next(), Option::some((3, 13))); assert_eq!(iter.next(), Option::some((4, 14))); assert_eq!(iter.next(), Option::none());
Run this example -
fn flatten(self: &mut Self) -> FlattenIterator<Self, T, iterable_yield_t<T>>
Flattens an iterator over iterable types into a single iterator.
Example
let iter = ["Hello", " ", "World"].iter().flatten(); let v = iter.to_vector(); defer v.free(); assert_eq!(v[..], &['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd']);
Run this example