簡體   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