[英]rust: Define a trait that returns a non consuming iterator. (associated type bounds for both T impls IntoIterator and &T impls IntoIterator)
[英]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.