3 回答
TA贡献1802条经验 获得超4个赞
的任一箱提供Either类型。如果两个Either都是迭代器,则Either:也是
extern crate either;
use either::Either;
use std::iter;
fn main() {
let x: Option<i64> = None;
// Repeat x 5 times if present, otherwise count from 1 to 5
let iter = match x {
None => Either::Left(1..5),
Some(x) => Either::Right(iter::repeat(x).take(5)),
};
for i in iter {
println!("{}", i);
}
}
像先前的答案一样,这仍然会占用每种具体类型的堆栈空间。但是,您不需要为每个具体值使用单独的变量。
也可以从函数返回此类型,这与trait对象引用不同。与盒装特征对象相比,无论选择哪种具体类型,它都将始终在堆栈上使用固定大小。
您还会在其他地方找到这种类型(或语义等效),例如 futures::Either
TA贡献1816条经验 获得超6个赞
您需要引用一个特征:
use std::iter;
fn main() {
let mut a;
let mut b;
let x: Option<i64> = None;
// Repeat x 5 times if present, otherwise count from 1 to 5
let iter: &mut Iterator<Item = i64> = match x {
None => {
a = 1..5;
&mut a
}
Some(x) => {
b = iter::repeat(x).take(5);
&mut b
}
};
for i in iter {
println!("{}", i);
}
}
该解决方案的主要缺点是,您必须为每种具体类型分配堆栈空间。这也意味着每种类型的变量。一件好事是只需要初始化使用的类型。
相同的想法但需要堆分配的是使用装箱的特征对象:
use std::iter;
fn main() {
let x: Option<i64> = None;
// Repeat x 5 times if present, otherwise count from 1 to 5
let iter: Box<Iterator<Item = i64>> = match x {
None => Box::new(1..5),
Some(x) => Box::new(iter::repeat(x).take(5)),
};
for i in iter {
println!("{}", i);
}
}
当您要从函数返回迭代器时,这最有用。占用的堆栈空间是单个指针,并且只会分配所需的堆空间。
TA贡献1811条经验 获得超4个赞
就个人而言,Either我通常更喜欢创建一系列Option<Iterator>链接在一起的价值观,而不是使用。像这样:
操场
use std::iter;
fn main() {
let x: Option<i64> = None;
// Repeat x 5 times if present, otherwise count from 1 to 5
for i in pick(x) {
println!("{}", i);
}
}
fn pick(opt_x: Option<i64>) -> impl Iterator<Item = i64> {
let iter_a = if let None = opt_x {
Some(1..5)
} else {
None
};
let iter_b = if let Some(x) = opt_x {
Some(iter::repeat(x).take(5))
} else {
None
};
iter_a.into_iter().flatten().chain(iter_b.into_iter().flatten())
}
与使用相比Either,它不那么明显,但是它避免了使用其他板条箱,有时效果非常好。
- 3 回答
- 0 关注
- 536 浏览
相关问题推荐
添加回答
举报