que*_*ter 1 iterator functional-programming type-conversion rust
struct A {...whatever...};
const MY_CONST_USIZE:usize = 127;
// somewhere in function
// vec1_of_A:Vec<A> vec2_of_A_refs:Vec<&A> have values from different data sources and have different inside_item types
let my_iterator;
if my_rand_condition() { // my_rand_condition is random and compiles for sake of simplicity
my_iterator = vec1_of_A.iter().map(|x| (MY_CONST_USIZE, &x)); // Map<Iter<Vec<A>>>
} else {
my_iterator = vec2_of_A_refs.iter().enumerate(); // Enumerate<Iter<Vec<&A>>>
}
Run Code Online (Sandbox Code Playgroud)
如何使这段代码编译?
最后(基于条件)我希望迭代器能够从两个输入构建,但我不知道如何将这些Map和Enumerate类型集成到单个变量中,而不调用collect()将迭代器具体化为Vec
欢迎阅读材料
在这种vec_of_A情况下,首先您需要在地图函数中替换&x为。x您拥有的代码永远不会编译,因为映射闭包尝试返回对其参数之一的引用,这在 Rust 中是不允许的。为了使类型匹配,您需要取消引用case&&A中的vec2_of_A_refsto&A而不是尝试添加对另一个的引用。
此外,-127是 的无效值usize,因此您需要选择一个有效值,或使用与 不同的类型usize。
解决这些问题后,现在您需要某种类型的动态调度。最简单的方法是装箱到Box<dyn Iterator>.
这是一个完整的例子:
#![allow(unused)]
#![allow(non_snake_case)]
struct A;
// Fixed to be a valid usize.
const MY_CONST_USIZE: usize = usize::MAX;
fn my_rand_condition() -> bool { todo!(); }
fn example() {
let vec1_of_A: Vec<A> = vec![];
let vec2_of_A_refs: Vec<&A> = vec![];
let my_iterator: Box<dyn Iterator<Item=(usize, &A)>>;
if my_rand_condition() {
// Fixed to return x instead of &x
my_iterator = Box::new(vec1_of_A.iter().map(|x| (MY_CONST_USIZE, x)));
} else {
// Added map to deref &&A to &A to make the types match
my_iterator = Box::new(vec2_of_A_refs.iter().map(|x| *x).enumerate());
}
for item in my_iterator {
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
(游乐场)
您还可以使用板条箱中的Either类型,而不是either装箱的特征对象。这是一个具有Left和Right变体的枚举,但如果左右类型也Either实现,则类型本身会实现,并且关联类型具有相同的类型。例如:IteratorItem
#![allow(unused)]
#![allow(non_snake_case)]
use either::Either;
struct A;
const MY_CONST_USIZE: usize = usize::MAX;
fn my_rand_condition() -> bool { todo!(); }
fn example() {
let vec1_of_A: Vec<A> = vec![];
let vec2_of_A_refs: Vec<&A> = vec![];
let my_iterator;
if my_rand_condition() {
my_iterator = Either::Left(vec1_of_A.iter().map(|x| (MY_CONST_USIZE, x)));
} else {
my_iterator = Either::Right(vec2_of_A_refs.iter().map(|x| *x).enumerate());
}
for item in my_iterator {
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
(游乐场)
为什么您会选择一种方法而不是另一种?
该方法的优点Either:
match这可能(但不能保证)比通过 vtable 查找的动态调度更快。盒装特征对象方法的优点:
Either对于两种以上的类型,该方法很快就会变得笨拙。| 归档时间: |
|
| 查看次数: |
641 次 |
| 最近记录: |