Hello,
Recently I experienced fun issue and thought it would be good to be in Iterator.
Iterator trait would be good to have methods for checking whether iterator instance is empty or not, before it is evaluated.
Of course, I can figure out the iterator is whether empty using next()
method.
But the problem is after I call next()
like method, it evaluates iterator.
What I just want to do is just adding some code logic to Iterator, without evaluating.
Fortunately, it is possible to do using existing methods, though it looks little bit verbose.
This code example below shows implementing or
,
fn main() {
// Case 1. if a is empty, then return b
let a = vec![];
let a = Box::new(a.into_iter());
let b = vec![4, 5, 6];
let b = Box::new(b.into_iter());
let c = or(a, b).collect::<Vec<i32>>();
println!("Case 1. [].or([4, 5, 6]) => {:?}", c);
assert_eq!(c, vec![4, 5, 6]);
// Case 2. if a is not empty, then return a
let a = vec![1, 2];
let a = Box::new(a.into_iter());
let b = vec![4, 5, 6];
let b = Box::new(b.into_iter());
let c = or(a, b).collect::<Vec<i32>>();
println!("Case 2. [1,2].or([4, 5, 6]) => {:?}", c);
assert_eq!(c, vec![1, 2]);
}
fn or(
a: Box<dyn Iterator<Item = i32>>,
b: Box<dyn Iterator<Item = i32>>
) -> Box<dyn Iterator<Item = i32>> {
let c = a
.map(|v| {
let is_a = true;
(is_a, v)
})
.chain({
let is_a = false;
b.map(move |v| {
(is_a, v)
})
})
.scan(true, |is_a_empty, (is_a, v)| {
match (&is_a_empty, is_a) {
(true, true) => {
*is_a_empty = false;
Some(v)
}
(true, false) => Some(v),
(false, true) => Some(v),
(false, false) => None,
}
});
Box::new(c)
}
What I wrote was (1)
which is combination of map-chain-scan
, but it can be replaced simply with or
.
Let's assume both A and B implemented Iterator trait.
-
A.or(B)
Return A if A is not empty, else if A is empty then return B.
Iterator B will be evaluated only if (A is evaluated and then A is empty) case.
Basically I got interested at first was only or
.
But if I add those feature, maybe it's natural to add other related methods:
-
and
,and_then
andor_else
(likeOption
andResult
enums have.)
How do you think of these?
[Updated]
Oh, sorry too too much. I shouldn't be rushed to do like this.
I changed the code example above,
and you can also execute it via this link below:
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=456892aa5dba1dd77e93cf077032b13f