やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

Rust自習(変数名でイテレートする方法)

 for item in vector {}のようにVec型の変数名だけで

成果物

参考

コード

$ cargo new into_iterator --bin

main.rs

struct Pixel {
    r: i8,
    g: i8,
    b: i8,
}
impl IntoIterator for Pixel {
    type Item = i8;
    type IntoIter = PixelIntoIterator;
    fn into_iter(self) -> Self::IntoIter {
        PixelIntoIterator {
            pixel: self,
            index: 0,
        }
    }
}
struct PixelIntoIterator {
    pixel: Pixel,
    index: usize,
}
impl Iterator for PixelIntoIterator {
    type Item = i8;
    fn next(&mut self) -> Option<i8> {
        let result = match self.index {
            0 => self.pixel.r,
            1 => self.pixel.g,
            2 => self.pixel.b,
            _ => return None,
        };
        self.index += 1;
        Some(result)
    }
}
impl<'a> IntoIterator for &'a Pixel {
    type Item = i8;
    type IntoIter = PixelIterator<'a>;
    fn into_iter(self) -> Self::IntoIter {
        PixelIterator {
            pixel: self,
            index: 0,
        }
    }
}
struct PixelIterator<'a> {
    pixel: &'a Pixel,
    index: usize,
}
impl<'a> Iterator for PixelIterator<'a> {
    type Item = i8;
    fn next(&mut self) -> Option<i8> {
        let result = match self.index {
            0 => self.pixel.r,
            1 => self.pixel.g,
            2 => self.pixel.b,
            _ => return None,
        };
        self.index += 1;
        Some(result)
    }
}
fn main() {
    let p = Pixel {
        r: 54,
        g: 23,
        b: 74,
    };
    for component in &p { println!("{}", component); }
    for component in &p { println!("{}", component); }
}
$ cargo run
54
23
74
54
23
74

 最後のfor文にて&pとしている。値が消費されず参照を返すだけなので何度でも呼び出せる。

所感

  • 冗長すぎる。値版と参照版はほぼ同じコード。&'aのところが違うだけ。DRYに書けない糞コードと言わざるを得ない。なんとかならんの?
  • iter(), iter_mut()の実装がしたいのに見つからない。自作の構造体でmap, filterなどのメソッドを使いたいのに。

対象環境

$ uname -a
Linux raspberrypi 4.19.42-v7+ #1219 SMP Tue May 14 21:20:58 BST 2019 armv7l GNU/Linux

前回まで