Rust 有条件地迭代几个可能的迭代器之一
我正试图根据一个Rust 有条件地迭代几个可能的迭代器之一,rust,Rust,我正试图根据一个选项输入将行为切换到函数。其思想是根据给定的选项是否存在进行迭代。下面是一个很小的例子,如果很傻的话: 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 match x { None => 1..5, Some
选项
输入将行为切换到函数。其思想是根据给定的选项是否存在进行迭代。下面是一个很小的例子,如果很傻的话:
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 match x {
None => 1..5,
Some(x) => iter::repeat(x).take(5),
} {
println!("{}", i);
}
}
使用std::iter;
fn main(){
设x:Option=None;
//如果存在,重复x 5次,否则从1数到5
因为我在x场比赛中{
无=>1..5,
一些(x)=>iter::repeat(x).take(5),
} {
println!(“{}”,i);
}
}
我得到一个错误:
错误[E0308]:匹配臂的类型不兼容
-->src/main.rs:7:14
|
7 |对于比赛x中的i{
| ______________^
8 | |无=>1..5,
9 | |一些(x)=>iter::重复(x)。取(5),
||--------------------------将arm与不兼容的类型匹配
10 | | } {
|| uuuuuu^应为结构'std::ops::Range',找到结构'std::iter::Take'`
|
=注意:应为'std::ops::Range'类型`
找到类型“std::iter::Take”`
当然,这很有道理,但我真的希望根据一个条件选择迭代器,因为for循环中的代码非常重要,复制粘贴所有这些只是为了更改迭代器选择,这将是非常难看和无法维护的
我试着在两个手臂上使用作为迭代器,但这给了我一个关于未大小类型的错误,因为它是一个trait对象。有没有一个简单的方法来实现这一点
当然,我可以使用.collect()
,因为它们返回相同的类型并在该向量上迭代。这是一个很好的快速修复方法,但对于大型列表来说似乎有点过分。最简单的解决方案是使用trait对象:
使用std::iter;
fn main(){
让我们做一个;
让mut b;
设x:Option=None;
//如果存在,重复x 5次,否则从1数到5
让iter:&mut-dyn迭代器=匹配x{
无=>{
a=1..5;
&穆塔
}
一些(x)=>{
b=iter::重复(x)。取(5);
&mut b
}
};
国际热核聚变实验堆{
println!(“{}”,i);
}
}
此解决方案的主要缺点是,您必须为每个具体类型分配堆栈空间。这也意味着每个类型都有变量。好的一点是,只需要初始化使用过的类型
与此相同,但需要堆分配的是使用装箱的trait对象:
使用std::iter;
fn main(){
设x:Option=None;
//如果存在,重复x 5次,否则从1数到5
让iter:Box=匹配x{
None=>Box::new(1..5),
Some(x)=>Box::new(iter::repeat(x).take(5)),
};
国际热核聚变实验堆{
println!(“{}”,i);
}
}
这在需要时非常有用。占用的堆栈空间是一个指针,只分配所需的堆空间
您也可以。最简单的解决方案是使用trait对象:
使用std::iter;
fn main(){
让我们做一个;
让mut b;
设x:Option=None;
//如果存在,重复x 5次,否则从1数到5
让iter:&mut-dyn迭代器=匹配x{
无=>{
a=1..5;
&穆塔
}
一些(x)=>{
b=iter::重复(x)。取(5);
&mut b
}
};
国际热核聚变实验堆{
println!(“{}”,i);
}
}
此解决方案的主要缺点是,您必须为每个具体类型分配堆栈空间。这也意味着每个类型都有变量。好的一点是,只需要初始化使用过的类型
与此相同,但需要堆分配的是使用装箱的trait对象:
使用std::iter;
fn main(){
设x:Option=None;
//如果存在,重复x 5次,否则从1数到5
让iter:Box=匹配x{
None=>Box::new(1..5),
Some(x)=>Box::new(iter::repeat(x).take(5)),
};
国际热核聚变实验堆{
println!(“{}”,i);
}
}
这在需要时非常有用。占用的堆栈空间是一个指针,只分配所需的堆空间
您也可以。提供类型。如果的两个部分都是迭代器,那么的两个部分都是迭代器:
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);
}
}
外部板条箱;
使用other::other;
使用std::iter;
fn main(){
设x:Option=None;
//如果存在,重复x 5次,否则从1数到5
让iter=match x{
None=>one::Left(1..5),
Some(x)=>other::Right(iter::repeat(x).take(5)),
};
国际热核聚变实验堆{
println!(“{}”,i);
}
}
比如,这仍然会占用每个具体类型的堆栈空间。但是,每个具体值不需要单独的变量
与trait对象引用不同,此类型也可以是。与装箱的trait对象相比,无论选择哪种具体类型,它在堆栈上始终使用固定大小
您也可以在其他地方找到此类型(或语义等价物),例如提供该类型的。如果或的两个部分都是迭代器,则或也是迭代器:
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);
}
}
外部板条箱;
使用other::other;
使用std::iter;
fn main(){
设x:Option=None;
//如果存在,重复x 5次,否则从1数到5
让iter=match x{
None=>one::Left(1..5),
Some(x)=>other::Right(iter::repeat(x).take(5)),
};
国际热核聚变实验堆{
println!(“{}”,i);
}
}
比如,这仍然会占用每个具体类型的堆栈空间。但是,每个具体值不需要单独的变量
与trait对象引用不同,此类型也可以是。与装箱的trait对象相比,无论选择哪种具体类型,它在堆栈上始终使用固定大小
我们在其他地方也会发现这种类型(或语义等价物)
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);
}
}
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())
}