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

```


## 10. ジェネリック




まずは最大値を求める例題を考える.

```rust

fn main() {
    
    let number_list = vec![34, 50, 25, 100, 65];
    
    let mut largest = number_list[0];
    
    for number in number_list {
        
        if number > largest {
            largest = number;
        }
    }
    
    println!("Thre largest number is {}", largest);
}
```


__最大値を求める関数__ を作ったとき、扱える__データ型__ をどうするかが、__ジェネリック__ を考える要因となるだろう


```rust
fn largest(number_list: &[i32]) -> i32 {
        
    let mut largest = number_list[0];
    
    for &number in number_list.iter() {
        
        if number > largest {
            largest = number;
        }
    }
    
    largest 
}



fn main() {
    
    let number_list = vec![34, 50, 25, 100, 65];
    
    let result = largest(&number_list);

    println!("Thre largest number is {}", result);
}
```

### 10.1 ジェネリックなデータ型



さて、__最大値を求める関数__ を、i32型とchar型にも対応する

とりあえずで書くとこうなって__いやな感じ__ がする

```rust
fn largest_i32(list: &[i32]) -> i32 {
    
    let mut largest = list[0];
    
    for &item in list.iter() {
        if item > largest {
            largest = item;
        }
    }
    
    largest
}

fn largest_char(list: &[char]) -> char {
    
    let mut largest = list[0];
    
    for &item in list.iter() {
        if item > largest {
            largest = item;
        }
    }
    
    largest
}

fn main() {
    
    let number_list = vec![34, 50, 25, 100, 65];
    
    let result = largest_i32(&number_list);

    println!("Thre largest number is {}", result);
    
    let char_list = vec!['y', 'm', 'a', 'q'];

    let result = largest_char(&char_list);
    println!("The largest char is {}", result);
}
```

型ごとにすべて準備するわけにはいかないよね

__そういうときにジェネリックを使おう!__ 

```rust
fn largest<T>(list: &[T]) -> T {

}
```

> 関数largestは、なんらかの型Tに関してジェネリックであると。 この関数にはlistという引数が1つあり、これは型Tの値のスライスです。 largest関数は同じT型の値を返します。


```rust
fn largest<T>(list: &[T]) -> T {
    
    let mut largest = list[0];
    
    for &item in list.iter() {
        if item > largest {
            largest = item;
        }
    }
    
    largest
}


fn main() {
    
    let number_list = vec![34, 50, 25, 100, 65];
    
    let result = largest(&number_list);

    println!("Thre largest number is {}", result);
    
    let char_list = vec!['y', 'm', 'a', 'q'];

    let result = largest(&char_list);
    println!("The largest char is {}", result);
}
```

ただし、このコードはまだ__コンパイル__が通りません。

のちほどわかるらしい


#### 構造定義で考える


__構造体の型__ もジェネリックで考えられるよ

```rust
struct Point<T> {
    x: T,
    y: T,
}

fn main() {
    
    let integer = Point { x: 5, y: 10 };
    let float = Point { x: 1.0, y: 4.0 };
}
```

ジェネリックは__複数の型__も利用できる

```rust

struct Point<U, T> {
    x: T,
    y: U,
}


fn main() {
    
    let integer = Point { x: 5, y: 10.0 };
    let float = Point { x: 1.0, y: 4 };
}
```


#### enum定義で考える

```rust

enum Option<T> {
    Some(T),
    None,
}


enum Result<T, E> {
    Ok(T),
    Err(E),
}

```


#### メソッド定義で考える

```Rust

struct Point<T> {
    x: T,
    y: T,
}


impl<T> Point<T> {
    fn x(&self) -> &T{
        &self.x
    }
}


fn main() {
    
    let p = Point { x:5, y:10};
    
    println!("p.x = {}", p.x());
}
```

__特定の型__ のみで利用できるメソッド定義

```rust
impl Point<f32> {
    fn distance_from_origin(&self) -> f32{
        (self.x.powi(2) + self.y.powi(2)).sqrt()
    }
}

```


```Rust

struct Point<T, U> {
    x: T,
    y: U,
}


impl<T, U> Point<T, U> {
    fn mixup<V, W>(self, other: Point<V, W>) -> Point<T, W> {
       Point {
           x: self.x,
           y: other.y,
       } 
    }
}


fn main() {
    let p1 = Point { x: 5, y: 10.4 };
    let p2 = Point { x: "Hello", y: 'c'};

    let p3 = p1.mixup(p2);

    println!("p3.x = {}, p3.y = {}", p3.x, p3.y);
}
````









次回は__トレイト__！


イエス！