rust - 有条件地迭代几个可能的迭代器之一

标签 rust

我正在尝试根据 Option 切换行为函数的输入。这个想法是根据给定的 Option 是否进行迭代。存在。这是一个最小的,如果愚蠢的例子:

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

我得到一个错误:

error[E0308]: match arms have incompatible types
  --> src/main.rs:7:14
   |
7  |       for i in match x {
   |  ______________^
8  | |         None => 1..5,
9  | |         Some(x) => iter::repeat(x).take(5),
   | |                    ----------------------- match arm with an incompatible type
10 | |     } {
   | |_____^ expected struct `std::ops::Range`, found struct `std::iter::Take`
   |
   = note: expected type `std::ops::Range<{integer}>`
              found type `std::iter::Take<std::iter::Repeat<i64>>`

当然,这非常有道理,但我真的很想根据条件选择迭代器,因为 for 循环中的代码非常重要,复制粘贴所有代码只是为了更改迭代器选择会非常丑陋且无法维护。

我尝试使用 as Iterator<Item = i64>在双臂上,但这给了我一个关于未定型类型的错误,因为它是一个特征对象。有解决此问题的简单方法吗?

我当然可以使用 .collect()因为它们返回相同的类型并迭代该向量。这是一个很好的快速修复,但对于大型列表来说似乎有点过分。

最佳答案

最直接的解决方案是使用特征对象:

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 dyn 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<dyn 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);
    }
}

这在您想要 return the iterator from a function 时最有用。 .占用的栈空间是单指针,只会分配需要的堆空间。

您也可以use an enum for each possible concrete iterator .

关于rust - 有条件地迭代几个可能的迭代器之一,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56932418/

相关文章:

types - 如何对依赖和嵌套求和类型进行建模?

rust - 在Rust中切换2d阵列中的列和行的最佳方法是什么?

rust - 具有特征边界的通用结构字段

rust - 迭代器查找 - 引用针而不是取消引用迭代项

json - 在递归结构中序列化 JSON

rust - 无法在Rust中的程序宏函数声明中打印

windows - 如何在 Windows 中的 Warp 等服务器应用程序上隐藏终端 shell?

rust - 如何显式收集 itertools::MinMax 结果向量?

winapi - 在 Rust 中实现 IWbemObjectSink 接口(interface)

rust - 如何编写宏来匹配略有不同的匹配语句?