我天真地试图这样做:
struct Foo<'a, S: Send, T:Send> {
next_:Box<Fn<(&'a mut S,), Option<T>> + Send>,
state:S
}
impl<'a, S: Send, T: Send> Iterator<T> for Foo<'a, S, T> {
fn next(&mut self) -> Option<T> {
return self.next_.call((&mut self.state,));
}
}
要创建迭代器,我可以使用闭包轻松地发送到任务。
但是,它会产生可怕的寿命不匹配错误:
<anon>:8:33: 8:48 error: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
<anon>:8 return self.next_.call((&mut self.state,));
^~~~~~~~~~~~~~~
<anon>:7:5: 9:6 help: consider using an explicit lifetime parameter as shown: fn next(&'a mut self) -> Option<T>
<anon>:7 fn next(&mut self) -> Option<T> {
<anon>:8 return self.next_.call((&mut self.state,));
<anon>:9 }
error: aborting due to previous error
playpen: application terminated with error code 101
我不明白这个错误。
闭包应采用生命周期为“a”的参数,即结构的生命周期。
国家为结构所有,因此其生命周期为“a”。
使用下一步。召唤((
所以这里的不匹配是下一个()中的自我终生和“呼叫中的a”之间的不匹配...但我不明白为什么它不是“a”。
修复上述代码的正确方法是什么?
有没有更好的方法来实现这一点?
游戏Geofence:http://is.gd/hyNi0S
您可以使用itertools
中的iterate
,完全满足您的需要。
否则,如果要将所有逻辑包含在闭包中而不使用状态概念,则可以通过以下方式实现:
struct IterClosure<T, C>(C) where C: FnMut() -> Option<T>;
impl<T, C> Iterator for IterClosure<T, C> where C: FnMut() -> Option<T>
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
(self.0)()
}
}
fn iter<T>(f: impl FnMut() -> Option<T>) -> impl Iterator<Item=T> {
IterClosure(f)
}
fn main() {
let mut it = (0..10).into_iter();
let mut closure = || it.next();
println!("{}", iter(closure).sum::<i32>());
let mut it = (0..10).into_iter();
iter(|| it.next()).for_each(
|i| println!("{}", i)
)
}
这是当前锈菌特性系统的一个不幸限制,它将很快被解除。这是因为缺少更高级的生命。据我所知,它的实施目前正在进行中。
让我们更仔细地检查你的结构定义(我已经删除了mut
,以允许使用'静态
进行进一步的推理,这并没有使它不那么普遍):
struct Foo<'a, S: Send, T:Send> {
next_: Box<Fn<(&'a S,), Option<T>> + Send>, // '
state: S
}
'a
寿命参数是此处的输入参数。这意味着它是由结构的用户提供的,而不是由其实现者提供的。
(顺便说一句,它不是结构实例的生存期——你不能仅用类型参数指定这样的生存期;它必须是自我
引用的生存期,你也不能使用它,因为迭代器
特征方法没有寿命参数。然而,这只是一个附带说明,与实际问题无关)
这意味着结构的用户可以任意选择'a
,包括选择大于结构生存期的生存期,例如'static
。现在观察这样的选择是如何改变结构的(只需将'static
替换为'a
):
struct FooStatic<S: Send, T: Send> {
next_: Box<Fn<(&'static S,), Option<T>> + Send>, // '
state: S
}
突然间,闭包只能接受'静态
引用,这显然不是您的案例-Next()
方法中自己
的生存期可能会更短,所以您不能将其传递给闭包。只有当自己的
生存期确实对应于'a
(如编译器所建议的)时,这才能工作:
fn next(&'a mut self) -> Option<T>
然而,正如我前面所说的,你们不能写这篇文章,因为它会违反合同。
使用更高的生存期,可以在闭包本身上指定生存期参数:
struct Foo<S: Send, T: Send> {
next_: Box<for<'a> Fn<(&'a mut S,), Option<T>> + Send>,
state: S
}
通过这种方式,闭包的生命周期参数由闭包的调用方选择,在这种情况下,它是迭代器
特征的实现者(即,您:),因此可以使用任何引用调用next
,包括对Foo
内部的引用。
这需要更高的秩生存期,因为闭包中的生存期不应该是类型签名的一部分:闭包只想采用
需要明确的是:代码失败是因为
next\uuu
只能使用至少存在'a
但
您现在可以使用旧的闭包来解决这个问题(本质上这就是
Fn
trait对象),甚至还有一个标准的库类型可以为您实现这一点:Unfold
。
迭代器模式允许你对一个项的序列进行某些处理。迭代器(iterator)负责遍历序列中的每一项和决定序列何时结束的逻辑。当使用迭代器时,我们无需重新实现这些逻辑。 在 Rust 中,迭代器是 惰性的(lazy),这意味着直到调用方法消费迭代器之前它都不会有效果。例如,示例 13-13 中的代码通过调用定义于 Vec 上的 iter 方法在一个 vector v1 上创建了一个迭代器。这段代码本身没有
看看我制作的以下类: 以及它在以下方面的用法: 如果我使用,可能令人惊讶的是,我将永远得不到无限流。 相反,代码将在底层方法中创建时永远循环。 到目前为止,这是纯理论上的,但如果我想首先跳过无限流中的前x个数字,然后用最后的y个数字来限制它,我可以明确地理解它的必要性,如下所示: 代码不会返回一个结果,应该怎么做呢?
为了决定使用哪个实现,我们需要知道哪个版本的 函数更快:直接使用 for 循环的版本还是使用迭代器的版本。 我们运行了一个性能测试,通过将阿瑟·柯南·道尔的“福尔摩斯探案集”的全部内容加载进 String 并寻找其中的单词 “the”。如下是 for 循环版本和迭代器版本的 search 函数的性能测试结果: 结果迭代器版本还要稍微快一点!这里我们将不会查看性能测试的代码,我们的目的并不是为了证明
是否可以从迭代器创建一个流,其中对象的序列与通过反复调用迭代器的next()方法生成的序列相同?我所考虑的具体情况涉及到Treeset.desceningIterator()返回的迭代器的使用,但是我可以想象在其他情况下,迭代器是可用的,而不是它所引用的集合。 例如,对于,我们可以编写并按照该集合的排序顺序获取该集合中的对象流,但是如果我们希望它们按照不同的顺序,比如通过使用获得的顺序呢?我想象的
我使用的是swift软件包车载套件,它需要一个我无法理解的特定闭包类型。类<code>OnboardPage</code>要求参数<code>action</code>的类型为<code>OnboardPageAction</code>。 这是我最新的尝试,我沿着这些路线尝试了几种变体。 XCode 失败,并显示错误消息: 无法转换类型为'(Bool,Error?) - 我到底做错了什么?错误是在