今年の言語はRust その３７

# 今年の言語はRust その３７

Rustを学びます

Rustの日本語ドキュメント 2nd Edition
https://doc.rust-jp.rs/book/second-edition/

オリジナル(英語)
https://doc.rust-lang.org/book/


## 実行環境

```sh
$ cargo -V
cargo 1.33.0 (f099fe94b 2019-02-12)

$ rustup -V
rustup 1.17.0 (069c88ed6 2019-03-05)

$ rustc --version
rustc 1.33.0 (2aa4c46cf 2019-02-28)

$  cat /proc/version
Linux version 4.14.97-74.72.amzn1.x86_64 (mockbuild@gobi-build-64002) 
(gcc version 7.2.1 20170915 (Red Hat 7.2.1-2) (GCC)) 
#1 SMP Tue Feb 5 20:59:30 UTC 2019

$ uname -a
Linux ip-10-100-0-8 4.14.97-74.72.amzn1.x86_64 
#1 SMP Tue Feb 5 20:59:30 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

$ cat /etc/\*release
NAME="Amazon Linux AMI"
VERSION="2018.03"
ID="amzn"
ID_LIKE="rhel fedora"
VERSION_ID="2018.03"
PRETTY_NAME="Amazon Linux AMI 2018.03"
ANSI_COLOR="0;33"
CPE_NAME="cpe:/o:amazon:linux:2018.03:ga"
HOME_URL="http://aws.amazon.com/amazon-linux-ami/"
Amazon Linux AMI release 2018.03

```

## 13. 関数型言語の機能: イテレータとクロージャ

### 13.2 一連の要素をイテレータで処理する

前回が眠くて意識もうろうとして進めていたので、復習します


> Rustにおいて、イテレータは怠惰です。つまり、イテレータを使い込んで消費するメソッドを呼ぶまで何の効果もないということです。

Python等をやっているとわかるのですが、
イテレータは呼び出されたときにだけ仕事をします。


ここでは、__ベクタ要素に対するイテレータ__ を __生成する__

と呼ばれています.


```rust
let v1 = vec![1, 2, 3];

let v1_iter = v1.iter(); // イテレータを生成する

for val in v1_iter {
    // {}でした
    println!("Got: {}", val);
}
```


#### Iteratorトレイトとnextメソッド

イテレータの定義はどこにあるのかというと

>全てのイテレータは、標準ライブラリで定義されているIteratorというトレイトを実装しています。 


まぁそのまんまです。

ただ、ここで、__type Item__ は新しい記法らしくいまは無視します。

nextメソッドが、Self::Itemを返しています。

まだこの章ではすべてを理解できなくて良さそう

```rust
pub trait Iterator {
    type Item;
    
    fn next(&mut self) -> Option<Self::Item>;
}
```


nextメソッドを使います

いろいろ注意があります　


```rust
#[test]
fn iterator_demostration() {
    
    let v1 = vec![1, 2, 3];
    
    let mut v1_iter = v1.iter();  // (注意1) mutable
    
    assert_eq!(v1_iter.next(), Some(&1)); // (注意2) nextはベクタの値への__不変な参照__ が返る
    assert_eq!(v1_iter.next(), Some(&2));
    assert_eq!(v1_iter.next(), Some(&3));
    assert_eq!(v1_iter.next(), None);
}

```

不変参照へのイテレータ : v1.ter()
v1の所有権を奪い、所有された値を返すイテレータ :  v1.into_iter()
可変参照へのイテレータ : v1.iter_mut()

#### イテレータを消費するメソッド

```rust
#[test]
fn iterator_sum() {
  let v1 = vec![1, 2, 3];

  let v1_iter = v1.iter();

  let total: i32 = v1_iter.sum();

  assert_eq!(total, 6);
}

```

#### ほかのイテレータを生成するメソッド

```rust
let v1: Vec<i32> = vec![1, 2, 3];

v1.iter().map(|x| x + 1);

```

上のコードはイテレータが使用されていないので、コンパイラから警告がでます。
collect()等をしようして__イテレータを消費__ したほうがよいでしょう

ここでは、イテレータをcollect()を使用してVecに戻していますね

pythonでいうとこんな感じかな。 -> list(range(5))


```rust
fn main() {
    
    let v1: Vec<i32> = vec![1, 2, 3];

    let v2: Vec<_> = v1.iter().map(|x| x + 1). collect();
    
    assert_eq!(v2, vec![2, 3, 4]);

}
```

#### 環境をキャプチャするクロージャを使用する


```rust

#[derive(PartialEq, Debug)]
struct Shoe {
    size: u32, 
    style: String,
}
```

所有権を奪っていることに注意

```rust
fn shoes_in_my_size(shoes: Vec<Shoe>, shoe_size: u32) -> Vec<Shoe> {
    shoes.into_iter()
        .filter(|s| s.size == shoe_size)
        .collect()
}
```

```rust
#[test]
fn filters_by_size() {
    
    let shoes = vec![
        Shoe { size:10, style: String::from("sneaker") },
        Shoe { size:13, style: String::from("sandal") },
        Shoe { size:10, style: String::from("boot") },
    ];
    
    let in_my_size = shoes_in_my_size(shoes, 10);
    
    assert_eq!(
        in_my_size,
        vec![
            Shoe { size:10, style: String::from("sneaker") },
            Shoe { size:10, style: String::from("boot") },
        ]
    );
    
}
```

#### Iteratorトレイトで独自のイテレータを作成する

```rust
struct Counter {
  count: u32,
}

impl Counter {
  fn new() -> Counter {
    Counter { count: 0}
  }
}

```

```rust
impl Iterator for Counter {
    type Item = u32;
    
    fn next(&mut self) -> Option<Self::Item> {
        self.count += 1;
        
        if self.count < 6{
            Some(self.count)
        }else{
            None
        }
    }
}

fn main() {
    
    let mut counter = Counter::new();
    
    assert_eq!(counter.next(), Some(1));
    assert_eq!(counter.next(), Some(2));
    assert_eq!(counter.next(), Some(3));
    assert_eq!(counter.next(), Some(4));
    assert_eq!(counter.next(), Some(5));
    assert_eq!(counter.next(), None);
}
```
今回は, counter.next()の返り値が、Some(1)となっています。前回はSome(&1)だったのに。。

前回はVecだったから、Vecの値への参照ということだったのかな。


#### ほかのIteratorトレイトメソッドを使用する

```rust

#[test]
fn using_other_iterator_trait_methods() {

  let sum: u32 = Counter::new().zip(Counter::new().skip(1))
                                .map(|(a, b)| a*b)
                                .filter(|x| x % 3 == 0)
                                .sum();

  assert_eq!(18, sum);

}
```

Linqっぽい感じになってます。

zip: 辞書化

map: イテレータ化

filter: フィルタリング

sum: 総和

賢いzipに注意: 

>zipは4組しか生成しないことに注意してください; 理論的な5番目の組の(5, None)は、 入力イテレータのどちらかがNoneを返したら、zipはNoneを返却するため、決して生成されることはありません。


イエス！