[英]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.