今年の言語は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. ジェネリック

### 10.2 トレイト

__共通のふるまいを定義する__

```rust
pub trait Summary {
    fn summarize(&self) -> String;
}
```

#### トレイトに型を実装する

```rust

// トレイト
pub trait Summary {
    fn summarize(&self) -> String;
}


// Type1
pub struct Tweet {
    pub username: String,
    pub content: String,
    pub reply: bool,
    pub retweet: bool,
}

impl Summary for Tweet {
    fn summarize(&self) -> String{
        format!("{}: {}", self.username, self.content)
    }
}

fn test(){
    let tweet = Tweet {
        username: String::from("hourse_ebooks"),
        content: String::from("of course, as you probably already know, people"),
        reply: false,
        retweet: false,
    };
    
    println!("1 new tweet: {}", tweet.summarize());
}




```



誤解を恐れずにいうならば、いわゆる__インターフェイス__か？


#### デフォルト実装

```Rust

// Trait
pub trait Summary {
    fn summarize(&self) -> String{
        String::from("(Read more.. )") // Default
    }
}

// Type2
pub struct NewsArticle {
    pub headline: String,
    pub location: String,
    pub author: String,
    pub content: String,
}

impl Summary for NewsArticle {
    // Use Default
}


fn main(){
    
    let article = NewsArticle {
        // ペンギンチームがスタンレーカップチャンピオンシップを勝ち取る！
        headline: String::from("Penguins win the Stanley Cup Championship!"),
        // ピッツバーグ、ペンシルベニア州、アメリカ
        location: String::from("Pittsburgh, PA, USA"),
        // アイスバーグ
        author: String::from("Iceburgh"),
        // ピッツバーグ・ペンギンが再度NHL(National Hockey League)で最強のホッケーチームになった
        content: String::from("The Pittsburgh Penguins once again are the best
        hockey team in the NHL."),
    };
    
    // 新しい記事が利用可能です！ {}
    println!("New article available! {}", article.summarize());
}
```

```Rust
New article available! (Read more.. Default)
```

これを

__NewsArticle 構造体__ の__Summary トレイト__　の**実装**と呼ぶ. (多分)

__型__ に__トレイト__ を実装するとも呼ぶ. (多分)



```rust
pub trait Summary {
    fn summarize_author(&self) -> String;

    fn summarize(&self) -> String {
        format!("(Read more.. ) {}", self.summarize_author()) // Default
    }
}

pub struct Tweet {
    pub username: String,
    pub content: String,
    pub reply: bool,
    pub retweet: bool,
}

impl Summary for Tweet {
    fn summarize_author(&self) -> String {
        format!("@{}", self.username)
    }
    
}


fn main(){
    let tweet = Tweet {
        username: String::from("hourse_ebooks"),
        content: String::from("of course, as you probably already know, people"),
        reply: false,
        retweet: false,
    };
    
    println!("1 new tweet: {}", tweet.summarize());
}
```

#### トレイト協会

これで、__トレイトの定義__ と __トレイトを型に実装__ する方法を知った
**ジェネリック**な型引数でトレイトを使用する方法を探求できる

```rust
pub fn notify<T: Summary>(item: T) {
    println!("Breaking news! {}", item.summarize())
}
```

以下はよくわからなかった (汗) 

Display, CLone, Debugは __まだわからない__


```rust
fn some_function<T: Display + Clone, U: Clone + Debug>(t: T, u: U) -> i32 {}

↓ 簡略化

fn sumo_function<T, U>(t: T, u: U) -> i32
    where T: Display + Clone,
          U: Clone + Debug {
}

```

気にせずガンガンすすめる

#### トレイト境界でlargest関数を修正する

__>__ 演算子は __std::cmp::PartialOrd__ で定義されている

> largestの本体で、大なり演算子(>)を使用して型Tの2つの値を比較したかったのです。その演算子は、 標準ライブラリトレイトのstd::cmp::PartialOrdでデフォルトメソッドとして定義されているので、 
largest関数が、比較できるあらゆる型のスライスに対して動くように、Tのトレイト境界にPartialOrdを指定する必要があります

```Rust
fn largest<T: PartialOrd>(list: &[T]) -> T {
    let mut largest = list[0];

    for &item in list.iter() {
        if item > largest {
            largest = item;
        }
    }

    largest
}

fn main() {

    // i32
    let number_list = vec![34, 50, 25, 100, 65];

    let result = largest(&number_list);
    println!("The largest number is {}", result);


    // char
    let char_list = vec!['y', 'm', 'a', 'q'];

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

```rust
error[E0508]: cannot move out of type `[T]`, a non-copy slice
(エラー: `[T]`、コピーでないスライスからムーブできません。)
 --> src/main.rs:2:23
  |
2 |     let mut largest = list[0];
  |                       ^^^^^^^
  |                       |
  |                       cannot move out of here
  |                       help: consider using a reference instead: `&list[0]`
                         (助言: 代わりに参照の使用を考慮してください: `&list[0]`)

error[E0507]: cannot move out of borrowed content
(エラー: 借用された内容からムーブできません)
 --> src/main.rs:4:9
  |
4 |     for &item in list.iter() {
  |         ^----
  |         ||
  |         |hint: to prevent move, use `ref item` or `ref mut item`
  |         cannot move out of borrowed content
            (ヒント: ムーブを避けるには、`ref item`か`ref mut item`を使用してください)
```

i32やcharのような既知のサイズの型は、 __スタック__ に格納できるので、 __Copy__ トレイトを実装している

なので __Copy__ もジェネリックとして実装する

```rust
fn largest<T: PartialOrd + Copy>(list: &[T]) -> T {
    let mut largest = list[0];

    for &item in list.iter() {
        if item > largest {
            largest = item;
        }
    }

    largest
}

===
The largest number is 100
The largest char is y

```

このCopyやPartialOrdもトレイト。

#### トレイト境界を使用して、メソッド実装を条件分けする

```Rust
use std::fmt::Display;

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

impl<T> Pair<T> {
    fn new(x: T, y: T) -> Self {
        Self {
            x,
            y,
        }
    }
}

impl<T: Display + PartialOrd> Pair<T> {
    fn cmp_display(&self) {
        if self.x >= self.y {
            println!("The largest member is x = {}", self.x);
        } else {
            println!("The largest member is y = {}", self.y);
        }
    }
}

fn main() {
    
}
```


次回はライフタイム！


イエス！