如何使用rust中的闭包创建迭代器?
我天真地尝试这样做:如何使用rust中的闭包创建迭代器?,rust,Rust,我天真地尝试这样做: 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) -> O
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,));
}
}
struct Foo+Send>,
州:S
}
恳求{
fn下一步(&mut self)->选项{
返回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 mut S
(因为它需要使用只保证在next
方法内部持续的数据调用函数:外部无法命名),不是类型签名中外部公开的(并且在某种程度上是可控的)生存期。这是不可能的,但我已经看到Niko Matsakis谈论过在IRC上进行这项工作,并且有类似这样的预拉请求,希望很快就会出现
需要明确的是:代码失败是因为下一步
只能使用至少存在'a
的引用调用,但是&mut self.state
只存在&mut self
,除非声明为&a mut self
,否则它不是'a
(这就是编译器建议它的原因)。添加此生存期是非法的,因为它不满足trait声明的要求
您现在可以使用旧的闭包来解决这个问题(本质上这就是Fn
trait对象),甚至还有一个标准的库类型可以为您做到这一点:。这是当前Rust的trait系统的一个不幸限制,它很快就会被取消。这是一种缺乏。据我所知,它的实施目前正在进行中
让我们更仔细地检查一下您的结构定义(我删除了mut
,以允许进一步使用“static
”进行推理,这并不会使它变得不那么通用):
突然,闭包只能接受静态的
引用,这显然不是您的情况-next()
方法中的self
的生存期可能更短,因此您不能将其传递到闭包中。只有当self
生存期确实对应于'a
(正如编译器所建议的那样)时,这才可能起作用:
fn next(&'a mut self)->选项
然而,正如我前面所说的,你们不能写这篇文章,因为它会违反合同
使用更高的生存期,可以在闭包本身上指定生存期参数:
struct Foo<S: Send, T: Send> {
next_: Box<for<'a> Fn<(&'a mut S,), Option<T>> + Send>,
state: S
}
structfoo{
下一步:框+发送>,
州:S
}
通过这种方式,闭包的生命周期参数由闭包的调用方选择,在这种情况下,它是迭代器
特征的实现者(即,您:),因此可以使用任何引用调用next
,包括对Foo
内部构件的引用。您可以从中使用它来做您需要的事情
否则,如果要将所有逻辑包含在闭包中而不使用
陈述您可以通过以下方式实施的概念:
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)
)
}
struct IterClosure(C),其中C:FnMut()->选项;
IterClosure的impl迭代器,其中C:FnMut()->Option
{
类型项=T;
fn下一步(&mut self)->选项{
(self.0)()
}
}
fn iter(f:impl FnMut()->Option)->impl迭代器{
环岛(f)
}
fn main(){
让mut it=(0..10).into_iter();
让mut闭包=| | it.next();
println!(“{}”,iter(闭包).sum::());
让mut it=(0..10).into_iter();
iter(| | it.next())。每个(
|i | println!(“{}”,i)
)
}
如果您需要,这里有一个展开示例:Rust现在已经打开了。这是更新答案的机会吗?
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
}
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)
)
}