Saya memiliki struct dengan Vec<nalgebra::Vector3<f32>>:

use nalgebra::Vector3;

struct VecOfVector {
    data: Vec<Vector3<f32>>,
}

fn float_iter_vector(vec: &mut Vector3<f32>) -> impl Iterator<Item = &mut f32> {
    vec.iter_mut()
}

Saya perlu mengimplementasikan IntoIterator untuk referensi yang dapat diubah ke struct ini dengan tipe Item menjadi &mut f32 (alias, ratakan menjadi iterator di atas f32). Ini dapat dilakukan dengan menggunakan flatten dan map, tetapi saya tidak yakin bagaimana menentukan tipe pengembalian untuk bagian map dari iterator.

Dari pemahaman saya, setiap fungsi memiliki tipe yang unik. Apakah ada cara untuk mengakses tipe spesifik ini (alias, fungsi mengembalikan iterator Map menggunakan fungsi persis ini)?

use std::iter::{Flatten, Map};
use std::slice::IterMut;

impl<'a> IntoIterator for &'a mut VecOfVector {
    type Item = &'a mut f32;

    // how do I specify type of "float_iter_vector"?
    type IntoIter = Flatten<Map<IterMut<'a, f32>, float_iter_vector>>;

    fn into_iter(self) -> Self::IntoIter {
        self.data.iter_mut().map(float_iter_vector).flatten()
    }
}

Saya dapat mengatasi masalah ini dengan tinju, tetapi saya khawatir ini akan menyebabkan iterator tidak disejajarkan dan digunakan dalam kode sensitif kinerja. Apakah LLVM masih dapat menyejajarkannya?

impl<'a> IntoIterator for &'a mut VecOfVector {
    type Item = &'a mut f32;

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

    fn into_iter(self) -> Self::IntoIter {
        Box::new(self.data.iter_mut().map(float_iter_vector).flatten())
    }
}

Atau, saya akan dengan senang hati menyelesaikan masalah ini menggunakan fitur type_alias_impl_trait, tetapi ini mengarah ke kesalahan seumur hidup yang saya pikir adalah bug kompiler.

#![feature(type_alias_impl_trait)]

impl<'a> IntoIterator for &'a mut VecOfVector {
    type Item = &'a mut f32;

    // hidden type error (likely compiler bug?)
    type IntoIter = impl Iterator<Item = &'a mut f32> + 'a;

    fn into_iter(self) -> Self::IntoIter {
        self.data.iter_mut().map(float_iter_vector).flatten()
    }
}

Saya memiliki ketiga versi kode ini di taman bermain di sini

Saya juga mengeposkan pertanyaan ini di r/rust

0
Ryan Greenblatt 10 Maret 2020, 16:51

1 menjawab

Jawaban Terbaik

Ini dijawab di r/rust oleh u/leo60228.

Anda harus secara eksplisit menentukan tipe iterator nalgebra. Ini menghasilkan sedikit sup umum (seperti kebanyakan hal di nalgebra): https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=715819c2b93592bae96f819bb020264f

use nalgebra::base::iter::MatrixIterMut;
use nalgebra::dimension::*;
use nalgebra::storage::Owned;
use nalgebra::Vector3;

struct VecOfVector {
    data: Vec<Vector3<f32>>,
}

fn float_iter_vector(vec: &mut Vector3<f32>) -> MatrixIterMut<f32, U3, U1, Owned<f32, U3, U1>> {
    vec.iter_mut()
}

type FloatIterVector =
    for<'a> fn(&'a mut Vector3<f32>) -> MatrixIterMut<'a, f32, U3, U1, Owned<f32, U3, U1>>;

use std::iter::{Flatten, Map};
use std::slice::IterMut;

impl<'a> IntoIterator for &'a mut VecOfVector {
    type Item = &'a mut f32;

    type IntoIter = Flatten<Map<IterMut<'a, Vector3<f32>>, FloatIterVector>>;

    fn into_iter(self) -> Self::IntoIter {
        self.data
            .iter_mut()
            .map(float_iter_vector as FloatIterVector)
            .flatten()
    }
}
0
Shepmaster 10 Maret 2020, 14:20