Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用rust中的闭包创建迭代器?_Rust - Fatal编程技术网

如何使用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)
    )
}