在 Rust 中使用迭代器组合实现“IntoIterator”时如何找到关联类型“IntoIter”?
How to find the associated type `IntoIter` when implementing `IntoIterator` by using iterator composition in Rust?
我目前正在尝试实现一个数组结构。我想以一种动态生成基本结构的方式为 SOA 实现 IntoIterator,就好像我在结构数组上进行迭代一样。这是类型:结构及其 SOA,
struct Particle {
x: f64,
y: f64,
v: [f64; 3]
}
struct ParticleSOA {
x: Vec<f64>,
y: Vec<f64>,
v: Vec<[f64; 3]>,
}
通过使用 itertools 中的 'izip!' 宏,通过压缩我的 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
函数的实现中推断类型,或者我唯一的选择是手动计算出由迭代器函数组合创建的精确类型?
编辑
秘诀就是摆脱闭包,尤其是隐藏在 izip 中的闭包!
Itertools 具有生成可用类型的 multizip 函数。
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])>
.
您可以 return 一个盒装迭代器,因此如果您的实现发生变化,return 类型不需要:
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>
比较复杂的类型。
你也可以创建自己的函数,而不是实现特征:
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 })
}
}
加上@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)
}
}
我目前正在尝试实现一个数组结构。我想以一种动态生成基本结构的方式为 SOA 实现 IntoIterator,就好像我在结构数组上进行迭代一样。这是类型:结构及其 SOA,
struct Particle {
x: f64,
y: f64,
v: [f64; 3]
}
struct ParticleSOA {
x: Vec<f64>,
y: Vec<f64>,
v: Vec<[f64; 3]>,
}
通过使用 itertools 中的 'izip!' 宏,通过压缩我的 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
函数的实现中推断类型,或者我唯一的选择是手动计算出由迭代器函数组合创建的精确类型?
编辑
秘诀就是摆脱闭包,尤其是隐藏在 izip 中的闭包! Itertools 具有生成可用类型的 multizip 函数。
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])>
.
您可以 return 一个盒装迭代器,因此如果您的实现发生变化,return 类型不需要:
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>
比较复杂的类型。
你也可以创建自己的函数,而不是实现特征:
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 })
}
}
加上@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)
}
}