[英]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 self
的FnMut
。 用伪代码:
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.