在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; }
}
Run Code Online (Sandbox Code Playgroud)
将它转换为迭代器是相当尴尬的,因为我需要存储一些代表每个分支的状态.
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
Run Code Online (Sandbox Code Playgroud)
通过上面的例子,这可以说是可以接受的(如果有点尴尬).考虑具有多个for循环,可变范围的情况,其中更难跟踪状态.
虽然我没有尝试这些,但我想有一些方法可以实现这一点,在大多数情况下,这些方法是不太理想的解决方法:
除了上面的解决方法:
是否有办法编写迭代器,如给出的示例,逻辑较少?
理想情况下更像是使用回调的示例.
否则有其他方法来处理这个?
或者这在Rust中根本不受支持?
注意,同样的逻辑适用于来自Python生成器(使用yield而不是回调,在这里使用回调作为示例,因为它们无处不在于第一类函数).
像C#和Python这样的语言提供了一种从使用特殊yield关键字编写的方法生成迭代器的方法.从Rust 1.11开始,该语言中没有这样的功能.但是,这样的功能是有计划的(参见RFC)(实际上,它yield是一个保留的关键字!)并且可能在C#中起作用(即编译器将生成具有必要状态和实现的结构Iterator).
在此期间,您可以尝试Stateful,一个试图提供此功能的项目.(此博客文章解释了有状态的工作方式以及所涉及的挑战.)
| 归档时间: |
|
| 查看次数: |
356 次 |
| 最近记录: |