Trait pushgen::traits::GeneratorExt
source · pub trait GeneratorExt: Sealed + Generator + Sized {
Show 62 methods
// Provided methods
fn all<F>(&mut self, predicate: F) -> bool
where F: FnMut(Self::Output) -> bool { ... }
fn any<F>(&mut self, predicate: F) -> bool
where F: FnMut(Self::Output) -> bool { ... }
fn cycle(self) -> Cycle<Self>
where Self: Clone { ... }
fn next(&mut self) -> Result<Self::Output, GeneratorResult> { ... }
fn next_back(&mut self) -> Result<Self::Output, GeneratorResult>
where Self: ReverseGenerator { ... }
fn last(self) -> Option<Self::Output> { ... }
fn cloned<'a, T>(self) -> Cloned<Self>
where Self: Generator<Output = &'a T>,
T: 'a + Clone { ... }
fn copied<'a, T>(self) -> Copied<Self>
where T: 'a + Copy,
Self: Generator<Output = &'a T> { ... }
fn chain<Gen>(self, other: Gen) -> Chain<Self, Gen>
where Gen: Generator<Output = Self::Output> { ... }
fn filter<Pred>(self, predicate: Pred) -> Filter<Self, Pred>
where Pred: FnMut(&Self::Output) -> bool { ... }
fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F>
where F: FnMut(Self::Output) -> Option<B> { ... }
fn map<Trans, Out>(self, transform_fn: Trans) -> Map<Self, Trans>
where Trans: FnMut(Self::Output) -> Out { ... }
fn skip(self, n: usize) -> Skip<Self> { ... }
fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P>
where P: FnMut(&Self::Output) -> bool { ... }
fn take(self, n: usize) -> Take<Self> { ... }
fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P>
where P: FnMut(&Self::Output) -> bool { ... }
fn flat_map<U, F>(self, f: F) -> Flatten<Map<Self, F>>
where U: IntoGenerator,
F: FnMut(Self::Output) -> U { ... }
fn flatten(self) -> Flatten<Self>
where Self::Output: IntoGenerator { ... }
fn for_each<Func>(&mut self, func: Func) -> GeneratorResult
where Func: FnMut(Self::Output) { ... }
fn try_for_each<F, E>(&mut self, f: F) -> Result<(), E>
where F: FnMut(Self::Output) -> Result<(), E> { ... }
fn zip<Right>(self, right: Right) -> Zip<Self, Right>
where Right: Generator { ... }
fn dedup(self) -> Dedup<Self>
where Self::Output: PartialEq { ... }
fn iter(self) -> IteratorAdaptor<Self> ⓘ { ... }
fn step_by(self, step_size: usize) -> StepBy<Self> { ... }
fn boxed(self) -> BoxedGenerator<Self::Output>
where Self: 'static { ... }
fn sum<S>(self) -> S
where S: Sum<Self::Output> { ... }
fn product<P>(self) -> P
where P: Product<Self::Output> { ... }
fn min(self) -> Option<Self::Output>
where Self::Output: Ord { ... }
fn min_by<F>(self, compare: F) -> Option<Self::Output>
where F: FnMut(&Self::Output, &Self::Output) -> Ordering { ... }
fn try_min_by<F>(
&mut self,
partial: Option<Self::Output>,
compare: F
) -> TryReduction<Option<Self::Output>>
where F: FnMut(&Self::Output, &Self::Output) -> Ordering { ... }
fn min_by_key<F, B>(self, f: F) -> Option<Self::Output>
where F: FnMut(&Self::Output) -> B,
B: Ord { ... }
fn max(self) -> Option<Self::Output>
where Self::Output: Ord { ... }
fn max_by<F>(self, compare: F) -> Option<Self::Output>
where F: FnMut(&Self::Output, &Self::Output) -> Ordering { ... }
fn try_max_by<F>(
&mut self,
partial: Option<Self::Output>,
compare: F
) -> TryReduction<Option<Self::Output>>
where F: FnMut(&Self::Output, &Self::Output) -> Ordering { ... }
fn max_by_key<F, B>(self, f: F) -> Option<Self::Output>
where F: FnMut(&Self::Output) -> B,
B: Ord { ... }
fn fold<B, F>(self, init: B, folder: F) -> B
where F: FnMut(B, Self::Output) -> B { ... }
fn try_fold<B, F, E>(
&mut self,
init: B,
folder: F
) -> Result<TryReduction<B>, E>
where F: FnMut(B, Self::Output) -> Result<B, E> { ... }
fn scan<State, F, B>(self, state: State, func: F) -> Scan<Self, State, F>
where F: FnMut(&mut State, Self::Output) -> Option<B> { ... }
fn reduce<F>(self, reducer: F) -> Option<Self::Output>
where F: FnMut(Self::Output, Self::Output) -> Self::Output { ... }
fn try_reduce<F>(
&mut self,
prev_reduction: Option<Self::Output>,
reducer: F
) -> TryReduction<Option<Self::Output>>
where F: FnMut(Self::Output, Self::Output) -> Self::Output { ... }
fn collect<B>(self) -> B
where B: FromGenerator<Self::Output> { ... }
fn enumerate(self) -> Enumerate<Self> { ... }
fn inspect<F>(self, inspector: F) -> Inspect<Self, F>
where F: FnMut(&Self::Output) { ... }
fn rev(self) -> Reverse<Self>
where Self: ReverseGenerator { ... }
fn by_ref(&mut self) -> &mut Self { ... }
fn position<P>(&mut self, predicate: P) -> Option<usize>
where P: FnMut(Self::Output) -> bool { ... }
fn find<P>(&mut self, predicate: P) -> Option<Self::Output>
where P: FnMut(&Self::Output) -> bool { ... }
fn find_map<B, F>(&mut self, f: F) -> Option<B>
where F: FnMut(Self::Output) -> Option<B> { ... }
fn count(self) -> usize { ... }
fn partition<Out, P>(self, partitioner: P) -> (Out, Out)
where Out: Default + Extend<Self::Output>,
P: FnMut(&Self::Output) -> bool { ... }
fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB)
where Self: Generator<Output = (A, B)>,
FromA: Default + Extend<A>,
FromB: Default + Extend<B> { ... }
fn partial_cmp<Rhs>(self, rhs: Rhs) -> Option<Ordering>
where Rhs: IntoGenerator,
Self::Output: PartialOrd<<Rhs as IntoGenerator>::Output> { ... }
fn partial_cmp_by<Rhs, Cmp>(self, rhs: Rhs, cmp: Cmp) -> Option<Ordering>
where Rhs: IntoGenerator,
Cmp: FnMut(Self::Output, Rhs::Output) -> Option<Ordering> { ... }
fn cmp<Rhs>(self, rhs: Rhs) -> Ordering
where Rhs: IntoGenerator<Output = Self::Output>,
Self::Output: Ord { ... }
fn cmp_by<Rhs, Cmp>(self, rhs: Rhs, cmp: Cmp) -> Ordering
where Rhs: IntoGenerator<Output = Self::Output>,
Cmp: FnMut(Self::Output, Self::Output) -> Ordering { ... }
fn lt<Rhs>(self, rhs: Rhs) -> bool
where Rhs: IntoGenerator,
Self::Output: PartialOrd<<Rhs as IntoGenerator>::Output> { ... }
fn le<Rhs>(self, rhs: Rhs) -> bool
where Rhs: IntoGenerator,
Self::Output: PartialOrd<<Rhs as IntoGenerator>::Output> { ... }
fn ge<Rhs>(self, rhs: Rhs) -> bool
where Rhs: IntoGenerator,
Self::Output: PartialOrd<<Rhs as IntoGenerator>::Output> { ... }
fn gt<Rhs>(self, rhs: Rhs) -> bool
where Rhs: IntoGenerator,
Self::Output: PartialOrd<<Rhs as IntoGenerator>::Output> { ... }
fn eq<Rhs>(self, rhs: Rhs) -> bool
where Rhs: IntoGenerator,
Self::Output: PartialEq<<Rhs as IntoGenerator>::Output> { ... }
fn ne<Rhs>(self, rhs: Rhs) -> bool
where Rhs: IntoGenerator,
Self::Output: PartialEq<<Rhs as IntoGenerator>::Output> { ... }
fn nth(&mut self, n: usize) -> Option<Self::Output> { ... }
}
Expand description
Provides extension-methods for all generators.
This allows generators to be composed to new generators, or consumed.
Example
use pushgen::{SliceGenerator, GeneratorExt};
let data = [1, 2, 3, 4];
let mut output: Vec<i32> = Vec::new();
SliceGenerator::new(&data).map(|x| x*3).for_each(|x| output.push(x));
assert_eq!(output, [3,6,9,12]);
Provided Methods§
sourcefn all<F>(&mut self, predicate: F) -> boolwhere
F: FnMut(Self::Output) -> bool,
fn all<F>(&mut self, predicate: F) -> boolwhere F: FnMut(Self::Output) -> bool,
Tests if every value from the generator matches a predicate.
all()
takes a closure that returns true
or false
. It applies this closure to each
value generated by the generator, and if they all return true
, then so does all()
. If
any value returns false
, all()
returns false
.
all()
is short-circuiting; it will stop processing as soon as it finds a false
.
An empty generator returns true.
Examples
Basic usage:
use pushgen::{IntoGenerator, GeneratorExt};
let a = [1, 2, 3];
assert!(a.into_gen().all(|x| x > 0));
assert!(!a.into_gen().all(|x| x > 2));
Stopping at first false:
use pushgen::{IntoGenerator, GeneratorExt};
let a = [1, 2, 3];
let mut gen = a.into_gen();
assert!(!gen.all(|x| x != 2));
assert_eq!(gen.iter().next(), Some(3));
sourcefn any<F>(&mut self, predicate: F) -> boolwhere
F: FnMut(Self::Output) -> bool,
fn any<F>(&mut self, predicate: F) -> boolwhere F: FnMut(Self::Output) -> bool,
Tests if any value matches a predicate.
any()
takes a closure that returns true
or false
. It applies
this closure to each value from the generator, and if any of them return
true
, then so does any()
. If they all return false
, it
returns false
.
any()
is short-circuiting; in other words, it will stop processing
as soon as it finds a true
, given that no matter what else happens,
the result will also be true
.
An empty generator returns false
.
Examples
Basic usage:
use pushgen::{IntoGenerator, GeneratorExt};
let a = [1, 2, 3];
assert!(a.into_gen().any(|x| x > 0));
assert!(!a.into_gen().any(|x| x > 5));
Stopping at the first true
:
use pushgen::{IntoGenerator, GeneratorExt};
let a = [1, 2, 3];
let mut gen = a.into_gen();
assert!(gen.any(|x| x != 2));
// we can still use `gen`, as there are more elements.
assert_eq!(gen.iter().next(), Some(2));
sourcefn cycle(self) -> Cycle<Self>where
Self: Clone,
fn cycle(self) -> Cycle<Self>where Self: Clone,
Repeats a generator endlessly.
Instead of stopping when a generator has completed, the generator will start over again from the beginning.
The generator will only start over once the source generator has completed. Spuriously stopping generators will not cause the source to start over again.
Examples
Basic usage:
use pushgen::{GeneratorExt, IntoGenerator};
let data = [1, 2, 3];
let mut gen = data.into_gen().cycle();
assert_eq!(gen.next(), Ok(1));
assert_eq!(gen.next(), Ok(2));
assert_eq!(gen.next(), Ok(3));
assert_eq!(gen.next(), Ok(1));
assert_eq!(gen.next(), Ok(2));
assert_eq!(gen.next(), Ok(3));
assert_eq!(gen.next(), Ok(1));
sourcefn next(&mut self) -> Result<Self::Output, GeneratorResult>
fn next(&mut self) -> Result<Self::Output, GeneratorResult>
Retrieve the next value from the generator
If the generator is completed or stopped before a value is retrieved an Err(GeneratorResult)
with the status of the generator is returned. Otherwise an Ok()
value is returned.
Examples
Basic usage:
use pushgen::{SliceGenerator, GeneratorExt, GeneratorResult};
let data = [1, 2];
let mut gen = SliceGenerator::new(&data);
assert_eq!(gen.next(), Ok(&1));
assert_eq!(gen.next(), Ok(&2));
assert_eq!(gen.next(), Err(GeneratorResult::Complete));
sourcefn next_back(&mut self) -> Result<Self::Output, GeneratorResult>where
Self: ReverseGenerator,
fn next_back(&mut self) -> Result<Self::Output, GeneratorResult>where Self: ReverseGenerator,
Get an element from the back of the generator.
This is analogous to next()
but gets values from the end.
Examples
Basic usage:
use pushgen::{SliceGenerator, GeneratorExt, GeneratorResult};
let data = [1, 2, 3];
let mut gen = SliceGenerator::new(&data);
assert_eq!(gen.next_back(), Ok(&3));
assert_eq!(gen.next_back(), Ok(&2));
assert_eq!(gen.next_back(), Ok(&1));
assert_eq!(gen.next_back(), Err(GeneratorResult::Complete));
sourcefn last(self) -> Option<Self::Output>
fn last(self) -> Option<Self::Output>
Exhausts the generator, returning the last element.
This method will evaluate the generator until it completes. While
doing so, it keeps track of the current element. After it completes
last()
will then return the last element it saw.
Examples
Basic usage:
use pushgen::IntoGenerator;
use pushgen::GeneratorExt;
let a = [1, 2, 3];
assert_eq!(a.into_gen().last(), Some(3));
let a = [1, 2, 3, 4, 5];
assert_eq!(a.into_gen().last(), Some(5));
sourcefn cloned<'a, T>(self) -> Cloned<Self>where
Self: Generator<Output = &'a T>,
T: 'a + Clone,
fn cloned<'a, T>(self) -> Cloned<Self>where Self: Generator<Output = &'a T>, T: 'a + Clone,
Creates a generator that clones all of its elements.
This is useful when you have a generator that generates &T
but you need a generate
that generates T
.
Examples
Basic usage
use pushgen::{SliceGenerator, GeneratorExt};
let data = [1, 2, 3];
let mut output: Vec<i32> = Vec::new();
SliceGenerator::new(&data).cloned().for_each(|x| output.push(x));
assert_eq!(output, [1, 2, 3])
sourcefn copied<'a, T>(self) -> Copied<Self>where
T: 'a + Copy,
Self: Generator<Output = &'a T>,
fn copied<'a, T>(self) -> Copied<Self>where T: 'a + Copy, Self: Generator<Output = &'a T>,
Creates a generator that copies all of its elements.
This is useful when you have a generator of &T
but need a generator of T
.
Examples
Basic usage:
use pushgen::{SliceGenerator, GeneratorExt};
let data = [1, 2, 3];
let mut v_copied: Vec<_> = Vec::new();
SliceGenerator::new(&data).copied().for_each(|x| v_copied.push(x));
assert_eq!(v_copied, [1, 2, 3]);
sourcefn chain<Gen>(self, other: Gen) -> Chain<Self, Gen>where
Gen: Generator<Output = Self::Output>,
fn chain<Gen>(self, other: Gen) -> Chain<Self, Gen>where Gen: Generator<Output = Self::Output>,
Creates a generator by chaining two generators, running them one after the other.
Example
use pushgen::{SliceGenerator, GeneratorExt};
let data = [1, 2, 3];
let mut output: Vec<i32> = Vec::new();
SliceGenerator::new(&data).chain(SliceGenerator::new(&data)).for_each(|x| output.push(*x));
assert_eq!(output, [1, 2, 3, 1, 2, 3]);
sourcefn filter<Pred>(self, predicate: Pred) -> Filter<Self, Pred>where
Pred: FnMut(&Self::Output) -> bool,
fn filter<Pred>(self, predicate: Pred) -> Filter<Self, Pred>where Pred: FnMut(&Self::Output) -> bool,
Create a filtered generator. Only values for which the predicate returns true will be passed on.
The predicate must implement FnMut(&Gen::Output) -> bool
.
Example
let input = [1,2,3,4];
let mut output: Vec<i32> = Vec::new();
let run_result = SliceGenerator::new(&input).filter(|x| *x % 2 == 0).for_each(|x| output.push(*x));
assert_eq!(run_result, GeneratorResult::Complete);
assert_eq!(output, [2,4]);
sourcefn filter_map<B, F>(self, f: F) -> FilterMap<Self, F>where
F: FnMut(Self::Output) -> Option<B>,
fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F>where F: FnMut(Self::Output) -> Option<B>,
Creates a generator that both filters and maps.
The returned generator produces only the value
s for which the supplied
closure returns Some(value)
.
filter_map
can be used to make chains of filter
and map
more
concise. The example below shows how a map().filter().map()
can be
shortened to a single call to filter_map
.
Examples
Basic usage:
use pushgen::{SliceGenerator, GeneratorExt};
let a = ["1", "two", "NaN", "four", "5"];
let mut output: Vec<i32> = Vec::new();
SliceGenerator::new(&a).filter_map(|s| s.parse().ok()).for_each(|x: i32| output.push(x));
assert_eq!(output, [1, 5]);
Here’s the same example, but with filter
and map
:
use pushgen::{SliceGenerator, GeneratorExt};
let a = ["1", "two", "NaN", "four", "5"];
let mut output: Vec<i32> = Vec::new();
SliceGenerator::new(&a).map(|s| s.parse()).filter(|s| s.is_ok()).map(|s| s.unwrap()).for_each(|x: i32| output.push(x));
assert_eq!(output, [1, 5]);
sourcefn map<Trans, Out>(self, transform_fn: Trans) -> Map<Self, Trans>where
Trans: FnMut(Self::Output) -> Out,
fn map<Trans, Out>(self, transform_fn: Trans) -> Map<Self, Trans>where Trans: FnMut(Self::Output) -> Out,
Takes a closure and creates a generator which calls the closure on each value.
Example
use pushgen::{SliceGenerator, GeneratorExt};
let data = [1, 2, 3];
let mut output: Vec<String> = Vec::new();
SliceGenerator::new(&data).map(|x| x.to_string()).for_each(|x| output.push(x));
assert_eq!(output, ["1", "2", "3"]);
sourcefn skip(self, n: usize) -> Skip<Self>
fn skip(self, n: usize) -> Skip<Self>
Skips over n
values, consuming and ignoring them.
Example
let input = [1,2,3,4];
let mut skipped_generator = SliceGenerator::new(&input).skip(2);
let mut output: Vec<i32> = Vec::new();
skipped_generator.for_each(|x| output.push(*x));
assert_eq!(output, [3,4]);
sourcefn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P>where
P: FnMut(&Self::Output) -> bool,
fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P>where P: FnMut(&Self::Output) -> bool,
Creates a generator that skips values based on a predicate.
skip_while()
takes a closure as argument. It will call this closure on each value,
and ignore values until the closure returns false
.
After false
is returned, skip_while()
will push the rest of the values.
Examples
Basic usage
use pushgen::{IntoGenerator, GeneratorExt};
let a = [-1i32, 0, 1];
let mut output = Vec::new();
a.into_gen().skip_while(|x| x.is_negative()).for_each(|x| output.push(x));
assert_eq!(output, [0, 1]);
sourcefn take(self, n: usize) -> Take<Self>
fn take(self, n: usize) -> Take<Self>
Takes n
values and then completes the generator.
Example
use pushgen::{SliceGenerator, GeneratorExt};
let data = [1, 2, 3, 4];
let mut output: Vec<i32> = Vec::new();
SliceGenerator::new(&data).take(2).for_each(|x| output.push(*x));
assert_eq!(output, [1, 2]);
sourcefn take_while<P>(self, predicate: P) -> TakeWhile<Self, P>where
P: FnMut(&Self::Output) -> bool,
fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P>where P: FnMut(&Self::Output) -> bool,
Creates a generator that pushes values based on a predicate.
take_while()
takes a closure as an argument. It will call this closure on each value
received from the source generator, and push values while it returns true. After false
is
returned, take_while()
’s job is over and it will always report Complete
.
Examples
Basic usage:
use pushgen::{IntoGenerator, GeneratorExt};
let a = [-1i32, 0, 1];
let mut gen_as_iter = a.into_gen().take_while(|x| x.is_negative()).iter();
assert_eq!(gen_as_iter.next(), Some(-1));
assert_eq!(gen_as_iter.next(), None);
sourcefn flat_map<U, F>(self, f: F) -> Flatten<Map<Self, F>>where
U: IntoGenerator,
F: FnMut(Self::Output) -> U,
fn flat_map<U, F>(self, f: F) -> Flatten<Map<Self, F>>where U: IntoGenerator, F: FnMut(Self::Output) -> U,
Creates a generator that works like map, but flattens nested structure.
The map
adapter is very useful, but only when the closure
argument produces values. If it produces a generator instead, there’s
an extra layer of indirection. flat_map()
will remove this extra layer
on its own.
You can think of flat_map(f)
as the semantic equivalent
of map
ping, and then flatten
ing as in map(f).flatten()
.
Another way of thinking about flat_map()
: map
’s closure returns
one item for each element, and flat_map()
’s closure returns an
iterator for each element.
Examples
Basic usage:
use pushgen::IntoGenerator;
use crate::pushgen::GeneratorExt;
let words = ["alpha", "beta", "gamma"];
let mut merged = String::new();
words.into_gen()
.flat_map(|s| pushgen::from_iter(s.chars()))
.for_each(|x| merged.push(x));
assert_eq!(merged, "alphabetagamma");
sourcefn flatten(self) -> Flatten<Self>where
Self::Output: IntoGenerator,
fn flatten(self) -> Flatten<Self>where Self::Output: IntoGenerator,
Creates a generator that flattens nested structure.
This is useful when you have a generator of generators or a generator of things that can be turned into generators and you want to remove one level of indirection.
Examples
Basic usage:
use pushgen::IntoGenerator;
use crate::pushgen::GeneratorExt;
let data = vec![vec![1, 2, 3, 4], vec![5, 6]];
let mut output: Vec<i32> = Vec::new();
let flattened = data.into_gen().flatten().for_each(|x| output.push(x));
assert_eq!(output, [1, 2, 3, 4, 5, 6]);
Mapping and then flattening:
use pushgen::IntoGenerator;
use crate::pushgen::GeneratorExt;
let words = &["alpha", "beta", "gamma"];
let mut merged = String::new();
words.into_gen()
.map(|s| pushgen::from_iter(s.chars()))
.flatten()
.for_each(|x| merged.push(x));
assert_eq!(merged, "alphabetagamma");
sourcefn for_each<Func>(&mut self, func: Func) -> GeneratorResultwhere
Func: FnMut(Self::Output),
fn for_each<Func>(&mut self, func: Func) -> GeneratorResultwhere Func: FnMut(Self::Output),
Run a generator to completion, or until it is stopped, and call a closure for each value produced by the generator.
The closure will be called for as long as the generator produces values, it is not possible
to abort processing early. If early abort is needed, use Generator::run
Example
let mut sum = 0i32;
let data = [1,2,3];
let result = SliceGenerator::new(&data).for_each(|x| sum += x);
assert_eq!(sum, 6);
assert_eq!(result, GeneratorResult::Complete);
sourcefn try_for_each<F, E>(&mut self, f: F) -> Result<(), E>where
F: FnMut(Self::Output) -> Result<(), E>,
fn try_for_each<F, E>(&mut self, f: F) -> Result<(), E>where F: FnMut(Self::Output) -> Result<(), E>,
A generator method that applies a fallible function to each item produced, stopping at the first error and returning that error.
This can also be thought of as the fallible form of for_each()
or as the stateless version of try_fold()
.
Examples
use std::fs::rename;
use std::io::{stdout, Write};
use std::path::Path;
use pushgen::{SliceGenerator, GeneratorExt};
let data = ["no_tea.txt", "stale_bread.json", "torrential_rain.png"];
let res = SliceGenerator::new(&data).try_for_each(|x| writeln!(stdout(), "{}", x));
assert!(res.is_ok());
let mut gen = SliceGenerator::new(&data);
let res = gen.try_for_each(|x| rename(x, Path::new(x).with_extension("old")));
assert!(res.is_err());
// It short-circuited, so the remaining items are still in the generator:
let mut output: Vec<&'static str> = Vec::new();
gen.for_each(|x| output.push(*x));
assert_eq!(output, ["stale_bread.json", "torrential_rain.png"]);
sourcefn zip<Right>(self, right: Right) -> Zip<Self, Right>where
Right: Generator,
fn zip<Right>(self, right: Right) -> Zip<Self, Right>where Right: Generator,
Zips the output of two generators into a single generator of pairs.
zip()
returns a new generator that will use values from two generators, outputting
a tuple where the first element comes from the first generator, and the second element comes
from the second generator.
The zip generator will complete when either generator completes.
Example
use pushgen::{SliceGenerator, GeneratorExt};
let left = [1, 2, 3];
let right = [4, 5, 6];
let mut output: Vec<(i32, i32)> = Vec::new();
SliceGenerator::new(&left).zip(SliceGenerator::new(&right)).for_each(|(a, b)| output.push((*a, *b)));
assert_eq!(output, [(1,4), (2, 5), (3, 6)]);
sourcefn dedup(self) -> Dedup<Self>where
Self::Output: PartialEq,
fn dedup(self) -> Dedup<Self>where Self::Output: PartialEq,
Create a de-duplicating generator, removing consecutive duplicate values.
Values will be made available when a non-duplicate is detected. If the up-stream generator generates
the following sequence: [1, 2, 3, 3, 4]
then the value 1
will be generated from the
Dedup
generator once the value 2
has been generated by the upstream generator and so
on.
Upstream value | Dedup-generated value |
---|---|
1 | None |
2 | 1 |
3 | 2 |
3 | Ignored |
4 | 3 |
Complete | 4 |
Complete | Complete |
Example
let data = [1, 2, 3, 3, 3, 3, 4, 3];
let mut output: Vec<i32> = Vec::new();
SliceGenerator::new(&data).dedup().for_each(|x| output.push(*x));
assert_eq!(output, [1, 2, 3, 4, 3]);
sourcefn iter(self) -> IteratorAdaptor<Self> ⓘ
fn iter(self) -> IteratorAdaptor<Self> ⓘ
Create an iterator from a generator.
This allows generators to be used in basic for-loops.
Example
use pushgen::{SliceGenerator, GeneratorExt};
let data = [1, 2, 3, 4, 5, 6];
let mut sum = 0;
for x in SliceGenerator::new(&data).iter() {
sum += x;
}
assert_eq!(sum, data.iter().sum());
sourcefn step_by(self, step_size: usize) -> StepBy<Self>
fn step_by(self, step_size: usize) -> StepBy<Self>
Create a generator that starts at the same point but steps by the given amount.
Note 1: The first value will always be generated, regardless of the step given
Panics
The method will panic if given a step size of 0
Examples
Basic usage:
use pushgen::{IntoGenerator, GeneratorExt, GeneratorResult};
let a = [0, 1, 2, 3, 4, 5];
let mut gen = a.into_gen().step_by(2);
assert_eq!(gen.next(), Ok(0));
assert_eq!(gen.next(), Ok(2));
assert_eq!(gen.next(), Ok(4));
assert_eq!(gen.next(), Err(GeneratorResult::Complete));
sourcefn boxed(self) -> BoxedGenerator<Self::Output>where
Self: 'static,
fn boxed(self) -> BoxedGenerator<Self::Output>where Self: 'static,
std
only.Box a generator, making it possible to use as return value in for instance traits.
Performance
This causes at least one layer of redirection, which is very likely to impact performance.
One should always prefer to use impl Generator<Output=X>
instead.
Example
use pushgen::{generators::BoxedGenerator, IntoGenerator, GeneratorExt};
fn make_generator() -> BoxedGenerator<i32> {
vec![1, 2, 3, 4].into_gen().map(|x| x*2).boxed()
}
let mut output = Vec::new();
make_generator().for_each(|x| output.push(x));
assert_eq!(output, [2, 4, 6, 8]);
sourcefn sum<S>(self) -> Swhere
S: Sum<Self::Output>,
fn sum<S>(self) -> Swhere S: Sum<Self::Output>,
Sums the values of a generator. Takes each value and adds them together and returns the result.
An empty generator returns the zero value of the type.
Spuriously stopping generators
sum()
only sums the values up until the source generator is first stopped. If the source
generator is not completed, but stops mid-generation for some reason, only the values up
until the first stop are summed.
Panics
When calling sum()
and a primitive integer type is being returned,
this method will panic if the computation overflows and debug assertions are enabled.
Examples
Basic usage:
use pushgen::{IntoGenerator, GeneratorExt};
let a = [1, 2, 3];
let sum: i32 = a.into_gen().sum();
assert_eq!(sum, 6);
sourcefn product<P>(self) -> Pwhere
P: Product<Self::Output>,
fn product<P>(self) -> Pwhere P: Product<Self::Output>,
Multiplies the values of a generator. Takes each value and adds them together and returns the result.
An empty generator returns the one value of the type.
Spuriously stopping generators
product()
only multiplies the values up until the source generator is first stopped. If the source
generator is not completed, but stops mid-generation for some reason, only the values up
until the first stop are multiplied.
Panics
When calling product()
and a primitive integer type is being returned,
this method will panic if the computation overflows and debug assertions are enabled.
Examples
Basic usage:
use pushgen::{GeneratorExt, from_iter};
fn factorial(n: u32) -> u32 {
// Create a generator from an iterable
from_iter((1..=n)).product()
}
assert_eq!(factorial(0), 1);
assert_eq!(factorial(1), 1);
assert_eq!(factorial(5), 120);
sourcefn min(self) -> Option<Self::Output>where
Self::Output: Ord,
fn min(self) -> Option<Self::Output>where Self::Output: Ord,
Returns the minimum value of a generator.
If several elements are equally minimum, the first element is
returned. If the generator is empty, None
is returned.
Spuriously stopping generators
min()
will return the result after the source generator has stopped. It doesn’t matter
if the source generator is stopped or completed.
Use try_min_by()
to handle spuriously stopping generators.
Examples
Basic usage:
use pushgen::{GeneratorExt, IntoGenerator};
let a = [1, 2, 3];
let b: Vec<u32> = Vec::new();
assert_eq!(a.into_gen().min(), Some(1));
assert_eq!(b.into_gen().min(), None);
sourcefn min_by<F>(self, compare: F) -> Option<Self::Output>where
F: FnMut(&Self::Output, &Self::Output) -> Ordering,
fn min_by<F>(self, compare: F) -> Option<Self::Output>where F: FnMut(&Self::Output, &Self::Output) -> Ordering,
Returns the value that gives the minimum value when compared with the specified comparison function.
If several elements are equally minimum, the first element is
returned. If the generator is empty, None
is returned.
Spuriously stopping generators
min_by()
will return the result after the source generator has stopped. It doesn’t matter
if the source generator is stopped or completed.
Use try_min_by()
to handle spuriously stopping generators.
Examples
use pushgen::{GeneratorExt, IntoGenerator};
let a = [-3_i32, 0, 1, 5, -10];
assert_eq!(a.into_gen().min_by(|x, y| x.cmp(y)).unwrap(), -10);
sourcefn try_min_by<F>(
&mut self,
partial: Option<Self::Output>,
compare: F
) -> TryReduction<Option<Self::Output>>where
F: FnMut(&Self::Output, &Self::Output) -> Ordering,
fn try_min_by<F>( &mut self, partial: Option<Self::Output>, compare: F ) -> TryReduction<Option<Self::Output>>where F: FnMut(&Self::Output, &Self::Output) -> Ordering,
Returns the value that gives the minimum value when compared with the specified comparison function.
If several elements are equally minimum, the first element is
returned. If the generator is empty, None
is returned.
This method can be used with spuriously stopping generators.
Examples
Basic usage
use pushgen::{GeneratorExt, IntoGenerator};
let a = [-3_i32, 0, 1, 5, -10];
assert_eq!(a.into_gen().try_min_by(None, |x, y| x.cmp(y)).unwrap(), Some(-10));
Stopping generator:
use pushgen::{Generator, ValueResult, GeneratorResult, GeneratorExt};
use pushgen::test::StoppingGen;
let data = [1, 2, 0, 4];
let mut gen = StoppingGen::new(1, &data);
let partial = gen.try_min_by(None, Ord::cmp);
// generator was stopped - indicated by a Partial reduction.
assert!(partial.is_partial());
let partial = partial.unwrap();
assert_eq!(partial, Some(&1));
// Feed partial value to continue reduction from the partial value
let res = gen.try_min_by(partial, Ord::cmp);
assert!(res.is_complete());
assert_eq!(res.unwrap(), Some(&0));
sourcefn min_by_key<F, B>(self, f: F) -> Option<Self::Output>where
F: FnMut(&Self::Output) -> B,
B: Ord,
fn min_by_key<F, B>(self, f: F) -> Option<Self::Output>where F: FnMut(&Self::Output) -> B, B: Ord,
Returns the value that gives the minimum value from the specified function.
If several elements are equally minimum, the first element is
returned. If the generator is empty, None
is returned.
Spuriously stopping generators
min_by_key()
will return the result after the source generator has stopped. It doesn’t matter
if the source generator is stopped or completed.
Manually use try_min_by()
to handle spuriously stopping generators.
Examples
use pushgen::{GeneratorExt, IntoGenerator};
let a = [-3_i32, 0, 1, 5, -10];
assert_eq!(a.into_gen().min_by_key(|x| x.abs()).unwrap(), 0);
sourcefn max(self) -> Option<Self::Output>where
Self::Output: Ord,
fn max(self) -> Option<Self::Output>where Self::Output: Ord,
Returns the maximum value of a generator.
If several elements are equally maximum, the last element is
returned. If the generator is empty, None
is returned.
Spuriously stopping generators
max()
will return the result after the source generator has stopped. It doesn’t matter
if the source generator is stopped or completed.
Use try_max_by()
to handle spuriously stopping generators.
Examples
Basic usage:
use pushgen::{GeneratorExt, IntoGenerator};
let a = [1, 2, 3];
let b: Vec<u32> = Vec::new();
assert_eq!(a.into_gen().max(), Some(3));
assert_eq!(b.into_gen().max(), None);
sourcefn max_by<F>(self, compare: F) -> Option<Self::Output>where
F: FnMut(&Self::Output, &Self::Output) -> Ordering,
fn max_by<F>(self, compare: F) -> Option<Self::Output>where F: FnMut(&Self::Output, &Self::Output) -> Ordering,
Returns the value that gives the maximum value when compared with the specified comparison function.
If several elements are equally maximum, the last element is
returned. If the generator is empty, None
is returned.
Spuriously stopping generators
max_by()
will return the result after the source generator has stopped. It doesn’t matter
if the source generator is stopped or completed.
Manually use try_max_by()
to handle spuriously stopping generators.
Examples
use pushgen::{GeneratorExt, IntoGenerator};
let a = [-3_i32, 0, 1, 5, -10];
assert_eq!(a.into_gen().max_by(|x, y| x.cmp(y)).unwrap(), 5);
sourcefn try_max_by<F>(
&mut self,
partial: Option<Self::Output>,
compare: F
) -> TryReduction<Option<Self::Output>>where
F: FnMut(&Self::Output, &Self::Output) -> Ordering,
fn try_max_by<F>( &mut self, partial: Option<Self::Output>, compare: F ) -> TryReduction<Option<Self::Output>>where F: FnMut(&Self::Output, &Self::Output) -> Ordering,
Returns the value that gives the maximum value when compared with the specified comparison function.
If several elements are equally maximum, the last element is
returned. If the generator is empty, None
is returned.
This method can be used with spuriously stopping generators.
Examples
Basic usage
use pushgen::{GeneratorExt, IntoGenerator};
let a = [-3_i32, 0, 1, 5, -10];
assert_eq!(a.into_gen().try_min_by(None, |x, y| x.cmp(y)).unwrap(), Some(-10));
Stopping generator:
use pushgen::{Generator, ValueResult, GeneratorResult, GeneratorExt};
use pushgen::test::StoppingGen;
let data = [1, 2, 0, 4];
let mut gen = StoppingGen::new(1, &data);
let partial = gen.try_max_by(None, Ord::cmp);
// generator was stopped - indicated by a Partial reduction.
assert!(partial.is_partial());
let partial = partial.unwrap();
assert_eq!(partial, Some(&1));
// Feed partial value to continue from the partial value
let res = gen.try_max_by(partial, Ord::cmp);
assert!(res.is_complete());
assert_eq!(res.unwrap(), Some(&4));
sourcefn max_by_key<F, B>(self, f: F) -> Option<Self::Output>where
F: FnMut(&Self::Output) -> B,
B: Ord,
fn max_by_key<F, B>(self, f: F) -> Option<Self::Output>where F: FnMut(&Self::Output) -> B, B: Ord,
Returns the value that gives the maximum value from the specified function.
If several elements are equally maximum, the last element is
returned. If the generator is empty, None
is returned.
Spuriously stopping generators
max_by_key()
will return the result after the source generator has stopped. It doesn’t matter
if the source generator is stopped or completed.
Manually use try_max_by()
to handle spuriously stopping generators.
Examples
use pushgen::{GeneratorExt, IntoGenerator};
let a = [-3_i32, 0, 1, 5, -10];
assert_eq!(a.into_gen().max_by_key(|x| x.abs()).unwrap(), -10);
sourcefn fold<B, F>(self, init: B, folder: F) -> Bwhere
F: FnMut(B, Self::Output) -> B,
fn fold<B, F>(self, init: B, folder: F) -> Bwhere F: FnMut(B, Self::Output) -> B,
Folds every element into an accumulator by applying an operation, returning the final result.
Folding is useful whenever you have a collection of something, and want to produce a single value from it.
Note: reduce()
can be used to use the first value as the initial value, if the accumulator
type and the output type is the same.
Spuriously stopping generators
fold()
will stop and return the result after the first stop of the generator. It doesn’t
matter if the generator stopped or completed.
Use try_fold()
to correctly handle spuriously stopping generators.
Arguments
init
The initial accumulator value
folder
A closure that takes an accumulator value and a generated value and returns a new
accumulator value.
Examples
Basic usage:
use pushgen::{IntoGenerator, GeneratorExt};
let a = [1, 2, 3];
// the sum of all of the elements of the array
let sum = a.into_gen().fold(0, |acc, x| acc + x);
assert_eq!(sum, 6);
sourcefn try_fold<B, F, E>(
&mut self,
init: B,
folder: F
) -> Result<TryReduction<B>, E>where
F: FnMut(B, Self::Output) -> Result<B, E>,
fn try_fold<B, F, E>( &mut self, init: B, folder: F ) -> Result<TryReduction<B>, E>where F: FnMut(B, Self::Output) -> Result<B, E>,
Apply a function as long as the return value is successful, producing a single final value.
try_fold()
takes two arguments: an initial value, and a closure with two arguments:
an ‘accumulator’, and a value.
The closure either returns successfully, with the value that the accumulator should have for
the next iteration, or it returns failure, with an error value that is propagated back to
the caller immediately (short-circuiting).
The return value from try_fold()
can distinguish between 3 different return-conditions:
Ok(Reduction::Complete(B))
-> the generator has completed and produced a final value.Ok(Reduction::Partial(B))
-> the generator spuriously stopped early. Latertry_fold
calls should use the partial value asinit
.Err(E)
-> The provided closure returned an error.
Examples
Basic usage:
use pushgen::{IntoGenerator, GeneratorExt, TryReduction};
let a = [1, 2, 3];
// the checked sum of all of the elements of the array
let sum = a.into_gen().try_fold(0i8, |acc, x| acc.checked_add(x).ok_or(()));
assert_eq!(sum, Ok(TryReduction::Complete(6)));
Short circuiting:
use pushgen::{IntoGenerator, GeneratorExt, TryReduction, GeneratorResult};
let a = [10, 20, 30, 100, 40, 50];
let mut gen = a.into_gen();
// This sum overflows when adding the 100 element
let sum = gen.try_fold(0i8, |acc, x| acc.checked_add(x).ok_or(()));
assert_eq!(sum, Err(()));
// Because it short-circuited, the remaining elements are still
// available through the iterator.
assert_eq!(gen.next(), Ok(40));
assert_eq!(gen.next(), Ok(50));
assert_eq!(gen.next(), Err(GeneratorResult::Complete));
sourcefn scan<State, F, B>(self, state: State, func: F) -> Scan<Self, State, F>where
F: FnMut(&mut State, Self::Output) -> Option<B>,
fn scan<State, F, B>(self, state: State, func: F) -> Scan<Self, State, F>where F: FnMut(&mut State, Self::Output) -> Option<B>,
An adaptor similar to fold
that holds internal state and produces a new generator.
Scan takes two arguments: an initial value of the internal state, and a closure with two arguments, the first being a mutable reference to the internal state, and the second being is the value generated.
The closure will be applied to each value generated by the source generator. If the closure
returns None
the generator is stopped with GeneratorResult::Stopped
, otherwise the value
returned in Some(value)
will be forwarded.
Examples
Basic usage:
use pushgen::{GeneratorResult, IntoGenerator, GeneratorExt};
let a = [1, 2, 3];
let mut gen = a.into_gen().scan(1, |state, x| {
*state = *state * x;
// yield negation of the state.
Some(-*state)
});
assert_eq!(gen.next(), Ok(-1));
assert_eq!(gen.next(), Ok(-2));
assert_eq!(gen.next(), Ok(-6));
assert_eq!(gen.next(), Err(GeneratorResult::Complete));
Stopping scan
use pushgen::{IntoGenerator, GeneratorExt, GeneratorResult};
let a = [1, 2, 3];
let mut gen = a.into_gen().scan(1, |state, x| {
*state = *state * x;
if x == 2 {
None // Will cause the generator to stop here!
}
else {
Some(-*state)
}
});
assert_eq!(gen.next(), Ok(-1));
assert_eq!(gen.next(), Err(GeneratorResult::Stopped));
assert_eq!(gen.next(), Ok(-6));
assert_eq!(gen.next(), Err(GeneratorResult::Complete));
sourcefn reduce<F>(self, reducer: F) -> Option<Self::Output>where
F: FnMut(Self::Output, Self::Output) -> Self::Output,
fn reduce<F>(self, reducer: F) -> Option<Self::Output>where F: FnMut(Self::Output, Self::Output) -> Self::Output,
Reduces the elements to a single one by repeatedly applying a reducing operation.
Returns
None
if the generator is empty, otherwise the result of the reduction.
Spuriously stopping generators
Reduce will return the result after the source generator has stopped. It doesn’t matter if the source generator is stopped or completed.
Use try_reduce
to reduce spuriously stopping generators.
Example
Find the maximum value:
use pushgen::{Generator, GeneratorExt, IntoGenerator};
fn find_max<G>(gen: G) -> Option<G::Output>
where G: Generator,
G::Output: Ord,
{
gen.reduce(|a, b| {
if a >= b { a } else { b }
})
}
let a = [10, 20, 5, -23, 0];
let b: [u32; 0] = [];
assert_eq!(find_max(a.into_gen()), Some(20));
assert_eq!(find_max(b.into_gen()), None);
sourcefn try_reduce<F>(
&mut self,
prev_reduction: Option<Self::Output>,
reducer: F
) -> TryReduction<Option<Self::Output>>where
F: FnMut(Self::Output, Self::Output) -> Self::Output,
fn try_reduce<F>( &mut self, prev_reduction: Option<Self::Output>, reducer: F ) -> TryReduction<Option<Self::Output>>where F: FnMut(Self::Output, Self::Output) -> Self::Output,
Reduces the values to a single value by repeatedly applying a reducing operation.
Use this reduction if the generator is known to spuriously stop mid-stream. Otherwise
it is better to use reduce()
.
Arguments
prev_reduction
The result of an earlier incomplete reduction. Set to None
if this is the
first reduction pass.
reducer
The reducing closure to use.
Returns
Ok(x)
if the generator was run to completion. x
is None
if the generator is empty,
otherwise it is the result of the complete reduction.
Err(y)
if the generator was stopped mid-reduction. y
is the value that the generator was
reduced to when it stopped. This value should be used in any subsequent calls to try_reduce
until an Ok()
value is returned.
Example
Find the maximum value:
use pushgen::{Generator, GeneratorExt, IntoGenerator, TryReduction};
fn find_max<G>(gen: &mut G) -> TryReduction<Option<G::Output>>
where G: Generator,
G::Output: Ord,
{
gen.try_reduce(None, |a, b| {
if a >= b { a } else { b }
})
}
let a = [10, 20, 5, -23, 0];
let b: [u32; 0] = [];
assert_eq!(find_max(&mut a.into_gen()).unwrap(), Some(20));
assert_eq!(find_max(&mut b.into_gen()).unwrap(), None);
With a stopping generator:
use pushgen::{Generator, ValueResult, GeneratorResult, GeneratorExt};
use pushgen::test::StoppingGen; // Available with feature `test`
let data = [1, 2, 3, 0, 4, 5];
let mut gen = StoppingGen::new(1, &data).copied();
let partial = gen.try_reduce(None, |a, b| a + b);
assert!(partial.is_partial());
let partial = partial.unwrap();
assert_eq!(partial, Some(1));
let res = gen.try_reduce(partial, |a, b| a + b);
assert!(res.is_complete());
assert_eq!(res.unwrap(), Some(1+2+3+4+5));
sourcefn collect<B>(self) -> Bwhere
B: FromGenerator<Self::Output>,
fn collect<B>(self) -> Bwhere B: FromGenerator<Self::Output>,
Transforms a generator into a collection.
collect()
can take any generator and turn it into a relevant collection.
Spuriously stopping generators
Collect will stop collecting values as soon as the generator is stopped. It doesn’t matter if the generator was completed or not.
To handle spuriously stopping generators one should manually do the collecting with for instance
for_each()
.
Examples
Basic usage:
use pushgen::{IntoGenerator, GeneratorExt};
let a = [1, 2, 3];
let doubled: Vec<i32> = a.into_gen()
.map(|x| x * 2)
.collect();
assert_eq!(vec![2, 4, 6], doubled);
sourcefn enumerate(self) -> Enumerate<Self>
fn enumerate(self) -> Enumerate<Self>
Creates a generator which gives the current generation count as well as the value.
The generator generates (i, val)
values, where i
is the current index of the value and
val
is the current value.
Overflow behaviour
The method does not guard against overflows, so enumerating more than usize::MAX
values
will either produce the wrong result or panic.
Panics
The generator might panic if the index overflows a usize
.
Examples
Basic usage:
use pushgen::{SliceGenerator, GeneratorExt, GeneratorResult};
let data = ['a', 'b', 'c'];
let mut gen = SliceGenerator::new(&data).enumerate();
assert_eq!(gen.next(), Ok((0, &'a')));
assert_eq!(gen.next(), Ok((1, &'b')));
assert_eq!(gen.next(), Ok((2, &'c')));
assert_eq!(gen.next(), Err(GeneratorResult::Complete));
sourcefn inspect<F>(self, inspector: F) -> Inspect<Self, F>where
F: FnMut(&Self::Output),
fn inspect<F>(self, inspector: F) -> Inspect<Self, F>where F: FnMut(&Self::Output),
Does something with each value from the generator, passing the value on.
This is useful if you want to inspect a value in the middle of a pipeline, for instance to add debug output.
Example
Basic usage:
use pushgen::{IntoGenerator, GeneratorExt};
let a = [1, 4, 2, 3];
// this iterator sequence is complex.
let sum = a.into_gen()
.filter(|x| x % 2 == 0)
.fold(0, |sum, i| sum + i);
println!("{}", sum);
// let's add some inspect() calls to investigate what's happening
let sum = a.into_gen()
.inspect(|x| println!("about to filter: {}", x))
.filter(|x| x % 2 == 0)
.inspect(|x| println!("made it through filter: {}", x))
.fold(0, |sum, i| sum + i);
println!("{}", sum);
This will print
6
about to filter: 1
about to filter: 4
made it through filter: 4
about to filter: 2
made it through filter: 2
about to filter: 3
6
sourcefn rev(self) -> Reverse<Self>where
Self: ReverseGenerator,
fn rev(self) -> Reverse<Self>where Self: ReverseGenerator,
Reverses a generators direction.
Examples
Basic usage:
use pushgen::{IntoGenerator, GeneratorExt, GeneratorResult};
let a = [1, 2, 3];
let mut gen = a.into_gen().rev();
assert_eq!(gen.next(), Ok(3));
assert_eq!(gen.next(), Ok(2));
assert_eq!(gen.next(), Ok(1));
assert_eq!(gen.next(), Err(GeneratorResult::Complete));
sourcefn by_ref(&mut self) -> &mut Self
fn by_ref(&mut self) -> &mut Self
Borrows a generator rather than consuming it.
This is useful to allow applying generator adaptors while still retaining ownership of the original generator.
Examples
Basic usage:
use pushgen::{IntoGenerator, GeneratorExt};
let mut words = ["hello", "world", "of", "rust"].into_gen();
let hello_world: Vec<_> = words.by_ref().take(2).collect();
assert_eq!(hello_world, ["hello", "world"]);
let of_rust: Vec<_> = words.collect();
assert_eq!(of_rust, ["of", "rust"]);
sourcefn position<P>(&mut self, predicate: P) -> Option<usize>where
P: FnMut(Self::Output) -> bool,
fn position<P>(&mut self, predicate: P) -> Option<usize>where P: FnMut(Self::Output) -> bool,
Searches for a value among the values generated, returning its index.
position()
takes a closure that returns true
or false
. This is applied to each value
and if one of them returns true, then position()
returns Some(index)
. Otherwise None
is returned.
position()
is short-circuiting; it will stop processing as soon as it finds a true
.
Panics
This function might panic if the generator generates more than usize::MAX
false
values.
Spuriously stopping generators
position()
does not attempt to handle spuriously stopping generators.
Examples
Basic usage:
use pushgen::{IntoGenerator, GeneratorExt};
let a = [1, 2, 3];
assert_eq!(a.into_gen().position(|x| x == 2), Some(1));
assert_eq!(a.into_gen().position(|x| x == 5), None);
Stopping at first true
:
use pushgen::{IntoGenerator, GeneratorExt};
let a = [1, 2, 3, 4];
let mut gen = a.into_gen();
assert_eq!(gen.position(|x| x >= 2), Some(1));
// we can still use `iter`, as there are more elements.
assert_eq!(gen.next(), Ok(3));
// The returned index depends on iterator state
assert_eq!(gen.position(|x| x == 4), Some(0));
sourcefn find<P>(&mut self, predicate: P) -> Option<Self::Output>where
P: FnMut(&Self::Output) -> bool,
fn find<P>(&mut self, predicate: P) -> Option<Self::Output>where P: FnMut(&Self::Output) -> bool,
Searches for a value that satisifes a predicate.
find()
takes a closure that returns true
or false
. This is applied to each value
and if one of them returns true, then find()
returns Some(value)
. Otherwise None
is returned.
find()
is short-circuiting; it will stop processing as soon as it finds a true
.
Spuriously stopping generators
find()
does not attempt to handle spuriously stopping generators. To handle spuriously
stopping generators, use try_fold()
. Another option is to use
gen.by_ref().filter(predicate).next()
.
Examples
Basic usage:
use pushgen::{GeneratorExt, IntoGenerator};
let a = [1, 2, 3];
assert_eq!(a.into_gen().find(|&x| x == 2), Some(2));
assert_eq!(a.into_gen().find(|&x| x == 5), None);
Stopping at the first true
:
use pushgen::{IntoGenerator, GeneratorExt};
let a = [1, 2, 3];
let mut gen = a.into_gen();
assert_eq!(gen.find(|&x| x == 2), Some(2));
// we can still use `iter`, as there are more elements.
assert_eq!(gen.next(), Ok(3));
sourcefn find_map<B, F>(&mut self, f: F) -> Option<B>where
F: FnMut(Self::Output) -> Option<B>,
fn find_map<B, F>(&mut self, f: F) -> Option<B>where F: FnMut(Self::Output) -> Option<B>,
Applies a function to the values and returns the first non-none result.
gen.find_map(f)
is equivalent to gen.by_ref().filter_map(f).next()
.
Spuriously stopping generators
find_map()
does not attempt to handle spuriously stopping generators.
Examples
Basic usage:
use pushgen::{IntoGenerator, GeneratorExt};
let a = ["lol", "NaN", "2", "5"];
let first_number = a.into_gen().find_map(|s| s.parse().ok());
assert_eq!(first_number, Some(2));
sourcefn count(self) -> usize
fn count(self) -> usize
Consumes the generator, counting the number of values generated and returning it.
Overflow behaviour
The method does no guarding against overflows, so counting more than usize::MAX
values
either produces the wrong result or panics. If debug assertions are enabled, a panic is guaranteed.
Panics
May panic if the generator generates more than usize::MAX
values.
Spuriously stopping generators
This method does not handle spuriously stopping generators. Use try_fold()
if the generator may spuriously stop generating values.
Examples
Basic usage:
use pushgen::{IntoGenerator, GeneratorExt};
let a = [1, 2, 3];
assert_eq!(a.into_gen().count(), 3);
let a = [1, 2, 3, 4, 5];
assert_eq!(a.into_gen().count(), 5);
sourcefn partition<Out, P>(self, partitioner: P) -> (Out, Out)where
Out: Default + Extend<Self::Output>,
P: FnMut(&Self::Output) -> bool,
fn partition<Out, P>(self, partitioner: P) -> (Out, Out)where Out: Default + Extend<Self::Output>, P: FnMut(&Self::Output) -> bool,
Consumes a generator, creating two collections from it.
The predicate passed to partition()
can return true, or false.
partition()
returns a pair: `(
Spuriously stopping generators
Partition will immediately stop once the generator has stopped. It doesn’t matter if the generator completes or spuriously stops.
Examples
Basic usage:
use pushgen::{IntoGenerator, GeneratorExt};
let a = [1, 2, 3, 4];
let (even, odd): (Vec<i32>, Vec<i32>) = a
.into_gen()
.partition(|&n| n % 2 == 0);
assert_eq!(even, vec![2, 4]);
assert_eq!(odd, vec![1, 3]);
Usage with spuriously stopping generator
use pushgen::{IntoGenerator, GeneratorExt};
let a = [1, 2, 3, 4];
// Use scan to create a "spuriously" stopping generator.
// Will generate the sequence [1, 2, *Stop*, 4].
let gen = a.into_gen().scan((), |_, value| {
if value == 3 {
None
}
else {
Some(value)
}
});
let (even, odd): (Vec<i32>, Vec<i32>) = gen.partition(|&x| x % 2 == 0);
assert_eq!(even, [2]); // Missing 4
assert_eq!(odd, [1]); // Missing 3
sourcefn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB)where
Self: Generator<Output = (A, B)>,
FromA: Default + Extend<A>,
FromB: Default + Extend<B>,
fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB)where Self: Generator<Output = (A, B)>, FromA: Default + Extend<A>, FromB: Default + Extend<B>,
Converts an iterator of pairs into a pair of containers.
unzip()
consumes a generator of pairs, producing two collections: one from the
left elements of the pairs, and one from the right elements.
Spuriously stopping generators
unzip()
will immediately stop once the generator has stopped. It doesn’t matter if the
generator completed or was stopped early.
Examples
Basic usage:
use pushgen::{IntoGenerator, GeneratorExt};
let a = [(1, 2), (3, 4)];
let (left, right): (Vec<_>, Vec<_>) = a.into_gen().unzip();
assert_eq!(left, [1, 3]);
assert_eq!(right, [2, 4]);
Spuriously stopping generator:
use pushgen::{IntoGenerator, GeneratorExt};
let a = [(1, 2), (3, 4), (5, 6), (7, 8)];
// Use scan to create a "spuriously" stopping generator.
fn scan_fn(_: &mut (), val: (i32, i32)) -> Option<(i32, i32)> {
if val.0 == 5 {
None
}
else {
Some(val)
}
}
let (left, right): (Vec<_>, Vec<_>) = a.into_gen().scan((), scan_fn).unzip();
assert_eq!(left, [1, 3]); // missing 5 and 7
assert_eq!(right, [2, 4]); // missing 6 and 8
// Behaviour consistent with iterator behaviour
let (left, right): (Vec<_>, Vec<_>) = a.iter().copied().scan((), scan_fn).unzip();
assert_eq!(left, [1, 3]); // missing 5 and 7
assert_eq!(right, [2, 4]); // missing 6 and 8
sourcefn partial_cmp<Rhs>(self, rhs: Rhs) -> Option<Ordering>where
Rhs: IntoGenerator,
Self::Output: PartialOrd<<Rhs as IntoGenerator>::Output>,
fn partial_cmp<Rhs>(self, rhs: Rhs) -> Option<Ordering>where Rhs: IntoGenerator, Self::Output: PartialOrd<<Rhs as IntoGenerator>::Output>,
Lexicographically compares the elements of this generator with those of another.
Spuriously stopping generators
partial_cmp()
will not work properly with spuriously stopping generators.
Examples
use std::cmp::Ordering;
use pushgen::{IntoGenerator, GeneratorExt};
let one = [1.];
let two = [1., 2.];
let nan = [f64::NAN];
assert_eq!(one.into_gen().partial_cmp(one), Some(Ordering::Equal));
assert_eq!(one.into_gen().partial_cmp(two), Some(Ordering::Less));
assert_eq!(two.into_gen().partial_cmp(one), Some(Ordering::Greater));
assert_eq!(nan.into_gen().partial_cmp(one), None);
sourcefn partial_cmp_by<Rhs, Cmp>(self, rhs: Rhs, cmp: Cmp) -> Option<Ordering>where
Rhs: IntoGenerator,
Cmp: FnMut(Self::Output, Rhs::Output) -> Option<Ordering>,
fn partial_cmp_by<Rhs, Cmp>(self, rhs: Rhs, cmp: Cmp) -> Option<Ordering>where Rhs: IntoGenerator, Cmp: FnMut(Self::Output, Rhs::Output) -> Option<Ordering>,
Lexicographically compares the elements of this generator with those of another using a supplied comparison function.
Spuriously stopping generators
partial_cmp_by()
will not work properly with spuriously stopping generators.
Examples
use std::cmp::Ordering;
use pushgen::{IntoGenerator, GeneratorExt};
let xs = [1.0, 2.0, 3.0, 4.0];
let ys = [1.0, 4.0, 9.0, 16.0];
assert_eq!(
(&xs).into_gen().partial_cmp_by(&ys, |&x, &y| x.partial_cmp(&y)),
Some(Ordering::Less)
);
assert_eq!(
(&xs).into_gen().partial_cmp_by(&ys, |&x, &y| (x * x).partial_cmp(&y)),
Some(Ordering::Equal)
);
assert_eq!(
(&xs).into_gen().partial_cmp_by(&ys, |&x, &y| (2.0 * x).partial_cmp(&y)),
Some(Ordering::Greater)
);
sourcefn cmp<Rhs>(self, rhs: Rhs) -> Orderingwhere
Rhs: IntoGenerator<Output = Self::Output>,
Self::Output: Ord,
fn cmp<Rhs>(self, rhs: Rhs) -> Orderingwhere Rhs: IntoGenerator<Output = Self::Output>, Self::Output: Ord,
Lexicographically compares the values of this generator with those of another.
Spuriously stopping generators
cmp()
does not work correctly with spuriously stopping generators.
Examples
use pushgen::{GeneratorExt, IntoGenerator};
use std::cmp::Ordering;
assert_eq!((&[1]).into_gen().cmp(&[1]), Ordering::Equal);
assert_eq!((&[1]).into_gen().cmp(&[1, 2]), Ordering::Less);
assert_eq!((&[1, 2]).into_gen().cmp(&[1]), Ordering::Greater);
sourcefn cmp_by<Rhs, Cmp>(self, rhs: Rhs, cmp: Cmp) -> Orderingwhere
Rhs: IntoGenerator<Output = Self::Output>,
Cmp: FnMut(Self::Output, Self::Output) -> Ordering,
fn cmp_by<Rhs, Cmp>(self, rhs: Rhs, cmp: Cmp) -> Orderingwhere Rhs: IntoGenerator<Output = Self::Output>, Cmp: FnMut(Self::Output, Self::Output) -> Ordering,
Lexicographically compares the values of this generator with those of another with respect to the specified comparison function.
Spuriously stopping generators
cmp_by()
does not work correctly with spuriously stopping generators.
Examples
use pushgen::{GeneratorExt, IntoGenerator};
use std::cmp::Ordering;
let xs = [1, 2, 3, 4];
let ys = [1, 4, 9, 16];
assert_eq!((&xs).into_gen().cmp_by(&ys, |&x, &y| x.cmp(&y)), Ordering::Less);
assert_eq!((&xs).into_gen().cmp_by(&ys, |&x, &y| (x * x).cmp(&y)), Ordering::Equal);
assert_eq!((&xs).into_gen().cmp_by(&ys, |&x, &y| (2 * x).cmp(&y)), Ordering::Greater);
sourcefn lt<Rhs>(self, rhs: Rhs) -> boolwhere
Rhs: IntoGenerator,
Self::Output: PartialOrd<<Rhs as IntoGenerator>::Output>,
fn lt<Rhs>(self, rhs: Rhs) -> boolwhere Rhs: IntoGenerator, Self::Output: PartialOrd<<Rhs as IntoGenerator>::Output>,
Determines if the values of this generator are lexicographically less than to those of another.
Spuriously stopping generators
lt()
will not work properly with spuriously stopping generators.
Examples
Basic usage
use pushgen::{GeneratorExt, IntoGenerator};
let one = [1];
let two = [1, 2];
assert_eq!((&one).into_gen().lt(&one), false);
assert_eq!((&one).into_gen().lt(&two), true);
assert_eq!((&two).into_gen().lt(&one), false);
assert_eq!((&two).into_gen().lt(&two), false);
sourcefn le<Rhs>(self, rhs: Rhs) -> boolwhere
Rhs: IntoGenerator,
Self::Output: PartialOrd<<Rhs as IntoGenerator>::Output>,
fn le<Rhs>(self, rhs: Rhs) -> boolwhere Rhs: IntoGenerator, Self::Output: PartialOrd<<Rhs as IntoGenerator>::Output>,
Determines if the values of this generator are lexicographically lesser or equal to those of another.
Spuriously stopping generators
le()
will not work properly with spuriously stopping generators.
Examples
Basic usage
use pushgen::{GeneratorExt, IntoGenerator};
let one = [1];
let two = [1, 2];
assert_eq!((&one).into_gen().le(&one), true);
assert_eq!((&one).into_gen().le(&two), true);
assert_eq!((&two).into_gen().le(&one), false);
assert_eq!((&two).into_gen().le(&two), true);
sourcefn ge<Rhs>(self, rhs: Rhs) -> boolwhere
Rhs: IntoGenerator,
Self::Output: PartialOrd<<Rhs as IntoGenerator>::Output>,
fn ge<Rhs>(self, rhs: Rhs) -> boolwhere Rhs: IntoGenerator, Self::Output: PartialOrd<<Rhs as IntoGenerator>::Output>,
Determines if the values of this generator are lexicographically greater or equal to those of another.
Spuriously stopping generators
ge()
will not work properly with spuriously stopping generators.
Examples
Basic usage
use pushgen::{GeneratorExt, IntoGenerator};
let one = &[1];
let two = &[1, 2];
assert_eq!(one.into_gen().ge(one.into_gen()), true);
assert_eq!(one.into_gen().ge(two.into_gen()), false);
assert_eq!(two.into_gen().ge(one.into_gen()), true);
assert_eq!(two.into_gen().ge(two.into_gen()), true);
sourcefn gt<Rhs>(self, rhs: Rhs) -> boolwhere
Rhs: IntoGenerator,
Self::Output: PartialOrd<<Rhs as IntoGenerator>::Output>,
fn gt<Rhs>(self, rhs: Rhs) -> boolwhere Rhs: IntoGenerator, Self::Output: PartialOrd<<Rhs as IntoGenerator>::Output>,
Determines if the values of this generator are lexicographically greater than those of another.
Spuriously stopping generators
gt()
will not work properly with spuriously stopping generators.
Examples
Basic usage
use pushgen::{GeneratorExt, IntoGenerator};
assert_eq!((&[1]).into_gen().gt(&[1]), false);
assert_eq!((&[1]).into_gen().gt(&[1, 2]), false);
assert_eq!((&[1, 2]).into_gen().gt(&[1]), true);
assert_eq!((&[1, 2]).into_gen().gt(&[1, 2]), false);
sourcefn eq<Rhs>(self, rhs: Rhs) -> boolwhere
Rhs: IntoGenerator,
Self::Output: PartialEq<<Rhs as IntoGenerator>::Output>,
fn eq<Rhs>(self, rhs: Rhs) -> boolwhere Rhs: IntoGenerator, Self::Output: PartialEq<<Rhs as IntoGenerator>::Output>,
Determines if the values from this generator are equal to those of another.
Spuriously stopping generators
eq()
will not work properly with spuriously stopping generators.
Examples
Basic usage
use pushgen::{GeneratorExt, IntoGenerator};
assert_eq!((&[1]).into_gen().eq(&[1]), true);
assert_eq!((&[1]).into_gen().eq(&[1, 2]), false);
sourcefn ne<Rhs>(self, rhs: Rhs) -> boolwhere
Rhs: IntoGenerator,
Self::Output: PartialEq<<Rhs as IntoGenerator>::Output>,
fn ne<Rhs>(self, rhs: Rhs) -> boolwhere Rhs: IntoGenerator, Self::Output: PartialEq<<Rhs as IntoGenerator>::Output>,
Determines if the values from this generator are unequal to those of another.
Spuriously stopping generators
ne()
will not work properly with spuriously stopping generators.
Examples
Basic usage
use pushgen::{GeneratorExt, IntoGenerator};
assert_eq!((&[1]).into_gen().ne(&[1]), false);
assert_eq!((&[1]).into_gen().ne(&[1, 2]), true);
sourcefn nth(&mut self, n: usize) -> Option<Self::Output>
fn nth(&mut self, n: usize) -> Option<Self::Output>
Returns the nth
value from the generator.
Like Iterator::nth
, the count starts from zero, so nth(0)
returns the first value,
nth(1)
the second and so on.
Spuriously stopping generators
nth()
will not work properly with spuriously stopping generators.
Examples
Basic usage:
use pushgen::{ GeneratorExt, IntoGenerator };
let a = [1, 2, 3];
assert_eq!((&a).into_gen().nth(1), Some(&2));