我希望能够编写甚至支持
genawaiter
板条箱的迭代器,并避免每个迭代器适配器的样板文件
我希望能够做到这一点(我知道我可以使用映射运算符,但这是当我需要在迭代器中拥有某些状态时的简化示例):
use genawaiter::{rc::gen, yield_};
use std::iter::Iterator;
fn wrap_with_option<Input, I: Iterator<Item = Input>>(iter: I) -> impl Iterator<Item = Option<Input>> {
return gen!({
for item in iter {
yield_!(Some(item));
}
})
.into_iter();
}
fn run() {
let input: Vec<i32> = vec![1, 2, 3, 4, 5];
let output: Vec<Option<&i32>> = input
.iter()
.compose(wrap_with_option)
.collect();
let expected = vec![
Some(&1),
Some(&2),
Some(&3),
Some(&4),
Some(&5)
];
assert_eq!(output, expected);
}
你可以这样做:
它将与任何获取迭代器并返回迭代器的函数一起使用,
它只是在全局迭代器上实现 compose 函数,获取一个函数并在当前迭代器(自身)上执行它并返回函数结果 - 新迭代器
use std::iter::Iterator;
pub trait ComposeByIterator: Iterator {
fn compose<F, OutputItem, OutputIterator>(self,f: F) -> OutputIterator
where
Self: Sized,
OutputIterator: Iterator<Item = OutputItem>,
F: Fn(Self) -> OutputIterator,
{
f(self)
}
}
impl<I: Iterator> ComposeByIterator for I {}
#[cfg(test)]
mod tests {
use genawaiter::{rc::gen, yield_};
use super::*;
#[test]
fn should_allow_changing_the_input_type() {
let input = vec![1, 2, 3, 4, 5];
let output: Vec<String> = input
.iter()
.compose(|iter| iter.map(|x| x.to_string()))
.collect();
let expected = vec![
"1".to_string(),
"2".to_string(),
"3".to_string(),
"4".to_string(),
"5".to_string(),
];
assert_eq!(output, expected);
}
#[test]
fn should_allow_multiple_compositions() {
let input = vec![1, 2, 3, 4, 5];
let output: Vec<String> = input
.iter()
.compose(|iter| iter.map(|x| x.to_string()))
.compose(|iter| iter.map(|x| x + "!"))
.collect();
let expected = vec![
"1!".to_string(),
"2!".to_string(),
"3!".to_string(),
"4!".to_string(),
"5!".to_string(),
];
assert_eq!(output, expected);
}
#[test]
fn should_allow_multiple_compositions_that_change_type() {
#[derive(Debug, PartialEq)]
struct MyStruct {
value: String,
}
let input = vec![1, 2, 3, 4, 5];
let output: Vec<MyStruct> = input
.iter()
.compose(|iter| iter.map(|x| x.to_string()))
.compose(|iter| iter.map(|x| MyStruct { value: x }))
.collect();
let expected = vec![
MyStruct {
value: "1".to_string(),
},
MyStruct {
value: "2".to_string(),
},
MyStruct {
value: "3".to_string(),
},
MyStruct {
value: "4".to_string(),
},
MyStruct {
value: "5".to_string(),
},
];
assert_eq!(output, expected);
}
#[test]
fn should_support_gen() {
fn wrap_with_option<Input, I: Iterator<Item = Input>>(iter: I) -> impl Iterator<Item = Option<Input>> {
return gen!({
for item in iter {
yield_!(Some(item));
}
})
.into_iter();
}
let input: Vec<i32> = vec![1, 2, 3, 4, 5];
let output: Vec<Option<&i32>> = input
.iter()
.compose(wrap_with_option)
.collect();
let expected = vec![
Some(&1),
Some(&2),
Some(&3),
Some(&4),
Some(&5)
];
assert_eq!(output, expected);
}
}