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())
}