今年の言語は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

```

## 18. パターンは値の構造に合致する

### 18.3 パターン記法

#### リテラルにマッチ

```rust
fn main() {

  let x = 1;

  match x {
    1 => println!("one"),
    2 => println!("two"),
    3 => println!("three"),
    _ => println!("other"),
  }
}
```

#### 名前付き変数にマッチする

※ 名前付き変数とはおそらく__Option::Some__ だと思われる

match式内のパターンとしてSomeを利用するのには注意が必要!!

Some(y)は、match式内の新しいスコープとして定義される。
その場合Some(y)はNone以外の値すべてに適合することになり、
以下のサンプルは__Matched, y=10__ を返す。

```rust

fn main() 
{

  let x = Some(5);
  let y = 10;

  match x {
    Some(50) => println!("Got 50"),
    Some(y) => println!("Matched, y={:?}", y),
    _ => println!("Default case x={:?}", x),
  }

  println!("at the end: x={:?}, y={:?}", x, y);
}
```

```bash
Matched, y=5
at the end: x=Some(5), y=10
```

#### 複数のパターン


数字の範囲を使用することができます

```rust

fn main() 
{

  let x = 5;

  match x {
    1 ... 5 => println!("one through five"),
    _ => println!("something else"),
  }

}

```

文字の範囲を使用することもできます
```rust

fn main() 
{

  let x = 'c';

  match x {
    'a' ... 'j' => println!("early ASCII letter"),
    'k' ... 'z' => println!("late ASCII letter"),
    _ => println!("something else"),
  }
}

```


#### 分配して値を分解する


見慣れない構文です。

構造体のフィールドの値に合致する変数おｗ生成しています。

```rust
struct Point {
  x: i32,
  y: i32,
}


fn main() 
{
  let p = Point {x:0, y:7};

  let Point {x:a, y:b} = p;

  assert_eq!(0, a);
  assert_eq!(7, b);

}
```

__構造体のフィールド__ を__パターン__ として使う

```rust
struct Point {
  x: i32,
  y: i32,
}


fn main() 
{
  let p = Point {x:0, y:7};

  match p {
    Point { x,   y:0 } => println!("On the x axis at {:?}", x),
    Point { x:0, y } => println!("On the y axis at {:?}", y),
    Point { x,   y } => println!("one neighter axis:({:?},{})", x, y),
  }
}
```


#### enumを分配する

```rust
enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(i32, i32, i32),
}

fn main() {
    let msg = Message::ChangeColor(0, 160, 255);

    match msg {
        Message::Quit => {
            // Quit列挙子には分配すべきデータがない
            println!("The Quit variant has no data to destructure.")
        },
        Message::Move { x, y } => {
            println!(
                // x方向に{}、y方向に{}だけ動く
                "Move in the x direction {} and in the y direction {}",
                x,
                y
            );
        }
        // テキストメッセージ: {}
        Message::Write(text) => println!("Text message: {}", text),
        Message::ChangeColor(r, g, b) => {
            println!(
                // 色を赤{}, 緑{}, 青{}に変更
                "Change the color to red {}, green {}, and blue {}",
                r,
                g,
                b
            )
        }
    }
}
```

#### 参照を分配する


```rust
struct Point {
  x: i32,
  y: i32,
}

fn main() {

  let points = vec![
      Point { x: 0, y: 0 },
      Point { x: 1, y: 5 },
      Point { x: 10, y: -3 },
  ];

  let _sum_of_squares: i32 = points
      .iter()
      .map(|&Point { x, y }| x * x + y * y)
      .sum();
}
```


#### 構造体とタプルを分配する

```rust
let ((feet, inches), Point{x,y}) = ((3, 10), Point{x:3, y:-10});
```



#### パターンの値を無視する

#### _ で値全体を無視する

関数の引数を意図的に無視することが可能

```rust
fn foo(_: i32, y:i32) {
  println!("{:?}", y);
}

fn main(){
  foo(3, 4);
}
```

> 関数の引数を無視することが特に有用なケースもあり、例えば、トレイトを実装する際、 特定の型シグニチャが必要だけれども、自分の実装の関数本体では引数の1つが必要ない時などです。 そうすれば、代わりに名前を使った場合のようには、未使用関数引数についてコンパイラが警告することはないでしょう。


#### ネストされた _ で値の一部を無視する

```rust
fn main() {

  let mut setting_value = Some(5);
  let new_setting_value = Some(10);

  match (setting_value, new_setting_value ) {
    (Some(_), Some(_)) => {
      println!("Cant overwrite an existing customized value");
    }

    _ => {
      setting_value = new_setting_value;
    }
  }

  println!("setting is {:?}", setting_value); 
}
```

#### 名前を_ で初めて未使用変数を無視する

↓はエラーになります。sが_sに借用されます。

```rust

fn main() {

  let s = Some(String::from("Hello"));

  if let Some(_s) = s {
    println!("found a string");
  }

  println!("{:?}", s);
}

===

error[E0382]: use of partially moved value: `s`
  --> H:\Dropbox\07_DevelopFolda\20190502_Rust\blog\src\main.rs:10:19
   |
6  |     if let Some(_s) = s {
   |                 -- value moved here
...
10 |     println!("{:?}", s);
   |                      ^ value used here after move
   |
   = note: move occurs because the value has type `std::string::String`, which does not implement the `Copy` trait

error: aborting due to previous error

For more information about this error, try `rustc --explain E0382`.
[Finished in 0.2s]
```

_ を使用することで借用を回避できます。

```rust

fn main() {

  let s = Some(String::from("Hello"));

  if let Some(_) = s {
    println!("found a string");
  }

  println!("{:?}", s);
}
```


#### .. で残りの部分を無視する

```rust
struct Point {
  x: i32,
  y: i32,
  z: i32,
}


fn main() {
  let origin = Point { x:0, y:0, z:0};

  match origin {
    Point {x, ..} => println!("x is {}", x)
  }
}
```

```rust
fn main() {
  let nubmers = (2, 4, 8, 16, 32);

  match nubmers {
    (first, .. , last) => {
      println!("{:?}, {}", first, last);
    }
  }
}
```

この章長いなー。途中で切ります。





イエス！