繁体   English   中英

从闭包返回并使用可变引用的迭代器

[英]Return and consume an iterator of mutable references from a closure

是否有使用关闭返回Iterator<Item = &mut T>的闭包的函数示例?

我想编写几个Rust函数,这些函数对集合的内容进行多次迭代,甚至可能向后迭代。 单独使用IntoIterator是不够的,因为它通过防止多次迭代的值来消耗其参数。 迭代器经常可以克隆,但是可变引用的迭代器。

如果我们真的只需要迭代集合的确切元素,则可以对所有Rust集合类型C使用&mut C: IntoIterator 接受RFC 2289语法,如下所示:

fn batch_normalization<II: ?Sized>(v: &mut II)
where
    for<'a> &'a mut II: IntoIterator<Item = &'a mut Self, IntoIter: DoubleEndedIterator + ExactSizeIterator>,

但是当前的形式碰到了一个编译器错误 同样,这将不允许用户使用迭代器适配器(例如map指定集合内容的“视图”。

直观地,我们应该使用一个闭包借用集合,该闭包在被调用时会重建我们的迭代器:

fn batch_normalization<F>(f: F)
where
    F: FnMut() -> impl Iterator<Item = &mut Self> + DoubleEndedIterator + ExactSizeIterator

我们还不能这样写,因为(a)关于impl Trait问题尚未解决,并且(b)我们的&mut Self需要一生,所以我们可以这样写:

fn batch_normalization<I, F: FnMut() -> I>(f: F)
where
    I: Iterator<Item = BorrowMut<Self>> + DoubleEndedIterator + ExactSizeIterator

我已经尝试过各种方法,但都没有用,主要是因为Item寿命超过了迭代器。

我们应该通过&'a mut C: IntoIterator<Item = &'a mut T>的方式来解决此问题,方法&'a mut C: IntoIterator<Item = &'a mut T>中将项目的生存期显式地绑定到&mut selfFnMut 用伪代码:

fn batch_normalization<I, F: FnMut() -> I>(f: F)
where
    I: for<'a: F::Output> Iterator<Item = &'a mut Self> + DoubleEndedIterator + ExactSizeIterator

实际应该如何从作为参数传递的闭包中返回Iterator<Item = &mut T> 应该总是使用一些fn指针混乱而不是关闭吗? 大致:

fn batch_normalization<'a, I, V: ?Sized>(v: &mut V, f: fn(&'a mut V) -> I)
where
    I: Iterator<Item = &'a mut Self> + DoubleEndedIterator + ExactSizeIterator 
{
   for x in f() { }
   // ...
   for x in f().rev() { } 
}

由于Fn*特性不支持将返回类型绑定到其self变量的生存期,因此无法使用闭包来精确地做到这一点。 现在, Fn*特征已被读取

pub trait FnOnce<Args> {
    type Output;
    extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
}
pub trait FnMut<Args>: FnOnce<Args> {
    extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
}
pub trait Fn<Args>: FnMut<Args> {
    extern "rust-call" fn call(&self, args: Args) -> Self::Output;
}

但这需要将这些特征读为

pub trait FnOnce<Args> {
    type Output<'fn>;
    extern "rust-call" fn call_once(self, args: Args) -> Self::Output<'static>;
}
pub trait FnMut<Args>: FnOnce<Args> {
    extern "rust-call" fn call_mut<'fn>(&'fn mut self, args: Args) -> Self::Output<'fn>;
}
pub trait Fn<Args>: FnMut<Args> {
    extern "rust-call" fn call<'fn>(&'fn self, args: Args) -> Self::Output<'fn>;
}

这些是不稳定的接口,因此它们最终可能会在RFC流程中进行更改,可能使用某些特殊的'fn liftime语法,例如FnMut() -> impl Iterator<Item = &'fn mut Self> ,甚至可能使用了参数化类型参数Args作为Args<'fn> Rust内部构件是此问题的合适论坛。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM