iterator - 编写支持多个逻辑分支的迭代器的最佳方法是什么?

标签 iterator rust

在 Rust 中,我开始编写迭代器,将它们从带有回调函数的代码中转换过来。

我遇到了一个问题,即在函数的多个分支中使用回调的代码没有完全转换为 Rust 迭代器。

给出一些伪代码。

// function using callbacks where the caller can exit at any time,
// can be used in a similar way to an iterator.
fn do_stuff(args, callback_fn(cb_args)) {
    // define a, b, c... args
    if callback_fn(a, b, 0) == false { return; }
    for i in 0..n {
        if callback_fn(c, d, i) == false { return; }
    }
    if callback_fn(e, f, -1) == false { return; }
}

将其转换为迭代器相当尴尬,因为我需要存储一些代表每个分支的状态。

impl Iterator for MyStruct {
    fn next(&mut self) -> Option<MyResult> {
        let out = match (self.state) {
            0 => {
                self.state += 1;
                Some(MyResult(self.a, self.b, 0))
            },
            1 => {
                self.i += 1;
                if self.i == self.n {
                    self.state += 1;
                }
                Some(MyResult(self.c, self.d, self.i - 1))
            },
            2 => {
                self.state += 1;
                Some(MyResult(self.e, self.f, -1))
            },
            _ => {
                None
            },
        }
        return out;
    }
// --- snip

对于上面的示例,这可以说是可以接受的(如果有点尴尬)。考虑具有多个 for 循环、变量范围的情况,在这些情况下跟踪状态要困难得多。


虽然我没有尝试这些,但我想有一些方法可以实现这一点,在大多数情况下都是不太理想的解决方法:

  • 使用回调版本,构建一个向量,然后对其进行迭代...
    (有效但违背了使用迭代器的目的,无法提前退出并避免为创建整个数据集例如)。
  • 编写一个迭代器,该迭代器与使用与回调版本类似的逻辑的线程通信。
    (虽然可能,但创建 OS 线程的开销使其在许多情况下成为一个糟糕的选择)。

除了上述解决方法:

有没有办法像给定的例子一样编写迭代器,逻辑更少?
理想情况下更像使用回调的例子。
否则还有其他方法可以处理吗?

或者这在 Rust 中根本不支持?


请注意,相同的逻辑适用于 Python 生成器(使用 yield 而不是回调,这里以回调为例,因为它们在一流函数中无处不在)。

最佳答案

C# 和 Python 等语言提供了一种从使用特殊 yield 关键字编写的方法生成迭代器的方法。从 Rust 1.11 开始,该语言中没有这样的功能。然而,这样的功能是计划中的(see RFC) (实际上,yield is a reserved keyword!)并且可能会像在 C# 中一样工作(即编译器会生成一个结构,其中包含 Iterator 的必要状态和实现)。

在此期间,您可以尝试 Stateful ,一个试图提供此功能的项目。 (This blog post 解释了 Stateful 的工作原理以及所涉及的挑战。)

关于iterator - 编写支持多个逻辑分支的迭代器的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39137063/

相关文章:

generics - 返回通用 Vec

rust - 为什么在全局范围内声明的枚举明确不需要终止分号?

java - 是否可以在 Java 中扩展迭代器的功能?

c++ - C++ 中的迭代器

javascript - Mustache.js 中数组元素的索引

generics - 为什么泛型的推断不是 "transitive"?

c++ - 从排序数组中删除重复项,不同代码方式的相同解决方案具有不同的输出

c++ - 获取 std::string 容器的 C 字符串迭代器

c++ - 无法使 rustc 使用 simd 指令进行包含范围循环

rust - 从另一个模块打印 vec 中的值 : field of struct is private