今年の言語は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.3 ライフタイムで参照を検証する

### 関数のジェネリックなライフタイム

長さを比較する関数を作って考えてみる.


二つの文字列スライスへの参照を受け取り、長さを比較して、 __長いほう__ のスライスを返したい。

しかし、以下のようにすると、ライフタイムに言及するエラーがおこる。

参照でもらったものを、参照で返す...

できそうだけど、Rustではできなさそう。


```rust
fn longest(x: &str, y: &str) -> &str {
    if x.len() > y.len() {
        x
    }else{
        y
    }
}

===
error[E0106]: missing lifetime specifier
 --> src/main.rs:1:33
  |
1 | fn longest(x: &str, y: &str) -> &str {
  |                                 ^ expected lifetime parameter
  |
  = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y`

```


ラフタイムを明示しよう


```rust
&i32

&'a i32

&'a mut i32
```


つまり

```Rust
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    }else{
        y
    }
}
==
コンパイル成功
```

書き換えたのは、(ただの)__参照 &str__ を、
__明示的なライフタイム付きの参照 &'a str__ に変更したことだ。


```rust
- fn longest(x: &str, y: &str) -> &str {
+ fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
```

(まだよくわからない)

ちなみに __'a__ でも __'b'__ でもOK!

```rust
fn longest<'b>(x: &'b str, y: &'b str) -> &'b str {}
```


>関数に関数外やからの参照がある場合、コンパイラは引数や戻り値のライフタイムをそれだけではじき出すことはほとんど不可能になります。 ライフタイムは、関数が呼び出される度に異なる可能性があります。このために、手動でライフタイムを注釈する必要があるのです。


(まだよくわからない)

#### longestに、__異なるライフタイムの2つ変数__ を渡して __具体的__ に考え見る


```rust
fn longest<'b>(x: &'b str, y: &'b str) -> &'b str {
    // 省略
}

fn main() {
    
    let string1 = String::from("long string is long"); // ライフタイム 長い
    
    {
        let string2 = String::from("xyz"); // ライフタイム 短い
        let result = longest(string1.as_str(), string2.as_str());
        
        println!("The longesst string is {}", result);
    }
    
}

==
コンパイル鰓ーなし
```


#### もう一つの例題

__これでわかるはず__

```rust
fn longest<'b>(x: &'b str, y: &'b str) -> &'b str {
    if x.len() > y.len() {
        x
    }else{
        y
    }
}

fn main() {
    
    let string1 = String::from("long string is long");          // 長いライフタイム
    let result;                                                 // 長いライフタイム
    
    {                                                           //
        let string2 = String::from("xyz");                      // 短いライフタイムスコープ
        result = longest(string1.as_str(), string2.as_str());   //
    }                                                           //
    
    println!("The longesst string is {}", result);              // 長いライフタイム
    
}
```

ここでは、


```sh

error[E0597]: `string2` does not live long enough
  --> src/main.rs:17:44
   |
17 |         result = longest(string1.as_str(), string2.as_str());
   |                                            ^^^^^^^ borrowed value does not live long enough
...
20 |     }
   |     - `string2` dropped here while still borrowed
21 |     
22 |     println!("The longesst string is {}", result);
   |                                           ------ borrow later used here
```


longest(x, y)に渡される引数と、　戻される変数の3つライフタイムが __異なる__　ことによりコンパイラに怒られている。

関数定義では__'a__として__一種類__のライフタイムしかしていされていない。

しかし、 __ライフタイムは短いほうを利用する__　規則に従うと、
longest<'a'> は __string2__ の短いラフサイクルを採用することになり、
ライフタイムの長いスコープ部のprintln!でresultが利用されている事がコンパイラに気づかれてしまい、怒られているのだ


(わかった)

体力をかなりうばわれたのでここまで。。


次回もまだまだ、ライフタイム!!


イエス！