簡體   English   中英

在 Rust 中使用迭代器組合實現“IntoIterator”時如何找到關聯類型“IntoIer”?

[英]How to find the associated type `IntoIer` when implementing `IntoIterator` by using iterator composition in Rust?

我目前正在嘗試實現 arrays 的結構。 我想以一種即時生成基本結構的方式為 SOA 實現 IntoIterator,就好像我在迭代結構數組一樣。 這是 to 類型:結構及其 SOA,

struct Particle {
    x: f64,
    y: f64,
    v: [f64; 3]
}

struct ParticleSOA {
    x: Vec<f64>,
    y: Vec<f64>,
    v: Vec<[f64; 3]>,
}

通過使用“izip!” 來自itertools的宏,通過壓縮我的 SOA 的Vec並將生成的元組映射到原始結構來構建迭代器非常容易。 但是,我無法找出IntoIterator特征所需的關聯類型IntoIter的類型。

impl IntoIterator for ParticleSOA{
    type Item = Particle;

    type IntoIter = ???;

    fn into_iter(self) -> Self::IntoIter {
       izip!(self.x,self.y,self.v).map(Particle::from)
    }
}

有沒有一種聰明的方法可以從我的into_iter function 的實現中推斷出類型,或者我唯一的選擇是手動計算出由迭代器函數組合創建的精確類型?

編輯

秘訣是擺脫閉包,尤其是隱藏在 izip 中的閉包。 Itertools 有一個 multizip function 可以產生一個可用的類型。

impl IntoIterator for ParticleSOA {
    type Item = Particle;

    fn into_iter(self) -> Self::IntoIter {
        multizip((self.x, self.y, self.v)).map(Particle::from)
    }

    type IntoIter = Map<
        itertools::Zip<(
            std::vec::IntoIter<f64>,
            std::vec::IntoIter<f64>,
            std::vec::IntoIter<[f64; 3]>,
        )>,
        fn((f64, f64, [f64; 3])) -> Particle,
    >;
}

注意:我的結構很方便地實現From<(f64, f64, [f64; 3])>

添加到@Netwave 所說的內容,使用不穩定的功能type_alias_impl_trait您可以在關聯類型中指定impl Iterator

#![feature(type_alias_impl_trait)]

impl IntoIterator for ParticleSOA {
    type Item = Particle;

    type IntoIter = impl Iterator<Item = Particle>;

    fn into_iter(self) -> Self::IntoIter {
       izip!(self.x,self.y,self.v).map(Particle::from)
    }
}

游樂場

您可以返回一個裝箱的迭代器,因此如果您的實現發生更改,則返回類型不需要:

use itertools::izip; // 0.10.3

struct Particle {
    x: f64,
    y: f64,
    v: [f64; 3]
}

struct ParticleSOA {
    x: Vec<f64>,
    y: Vec<f64>,
    v: Vec<[f64; 3]>,
}

impl IntoIterator for ParticleSOA{
    type Item = Particle;

    type IntoIter = Box<dyn Iterator<Item=Self::Item>>;

    fn into_iter(self) -> Self::IntoIter {
       Box::new(izip!(self.x,self.y,self.v).map(|(x, y, v)| Particle {x, y , v}))
    }
}

操場

否則,類型應該是近似值,例如:

Map<Zip<(f64, f64, [f64; 3])>, Fn>

一個相當復雜的類型。

您也可以制作自己的 function,而不是實現特征:

impl ParticleSOA {
    #[inline]
    fn into_iter(self) -> impl Iterator<Item=Particle> {
        izip!(self.x, self.y, self.v).map(|(x, y, v)| Particle { x, y, v })
    }
}

操場

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM