RubyからRustに移行について

# RubyのエンジニアはRustの最初に困ったこと
- 気持ち：　他の言語とくらべると、考えりが違います。
- いくつか新しい言葉がありますので、困ります。 (mut, ownership, trait, )
- 最初に簡単な関数を書きましたが、ビルドでエラーは良く発生しました。

---

# 現在
- ユニークビジョン株式会社ではRubyをRustに変えています。
- 心理的にRubyをRustに簡単に変えるように説明します。

---

# Class/def VS Struct / impl 
## Rubyでは
- Class / def 
- データを持つ
- 処理を定義する

```ruby
class User
   def initialize(id, name, addr)
      @id = id
      @name = name
      @addr = addr
   end
   
   def hello
      puts "hello #{@name}"
   end

end

user1 = User.new(1, 'hoge', 'aaaaaa')
user1.hello()

```

---

## Rustでは
- Classがありません
- データもつはStructを使います
- 処理はStructにimplを使います

```rust
struct User {
    id: u64,
    name: String,
    addr: String,
}


impl User {
    fn hello(&self) {
        println!("Hello {}", self.name);
    }
}


fn main() {
    let user1 = User {
        id: 1,
        name: String::from("hoge"),
        addr: String::from("aaaaaa"),
    };
    user1.hello()
}

```

---

# Module vs Trait

## RubyのModule
- 処理は別で定義出来ます

```ruby
module Cream
  def cream
    puts "Hello Qiita User"
  end
end

class Cookie
  include Cream
end

cookie = Cookie.new
cookie.cream
```

---

## RustのTrait
- 処理も別で定義出来ます

```rust
trait Cream {
    fn cream(&self) {
        println!("Hello Qiita User");
    }
}

struct Cookie { }

impl Cream for Cookie { }

fn main() {
   let cookie = Cookie { };
   cookie.cream()
}


```

---

## 他の言語と似てるものは
- abstract class
- interface 

---

# 変数/Type
## Rubyでは
- 変数のTypeは明確の定義ががありません。

```ruby

a = 1 
puts a.class
a = "helo"
puts a.class


```

結果

```
Integer
String
```

---

## Rustでは
- 変数の値のデフォルトは変更不可
- 変数の型は固定
- Mut / OwnerShipの概念があり: https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html

```rust

fn print_type_of<T>(_: T) {
    println!("{}", std::any::type_name::<T>())
}

fn main() {
let a = "aa";
a = "bb"
}


```

error[E0384]: cannot assign twice to immutable variable `a`

```rust 
fn main() {
let mut a = "aa";
a = 1
}

```
error[E0308]: mismatched types

---

## つまり
- Rustはメモリー管理は厳しいので、変数と型の定義も厳しいです。
- 慣れるだけじゃなく、新しい変数を使うときに、この変数は必要かどうかをちゃんと考えないといけません。

---

# Result/Error の考えり
## Rubyでは
- ロジックを集中にして、動作確認して、そのあとにエラーハンドリングをやります。
# 処理開発

```ruby

GaibuAPI1::execute()
GaibuAPI2::execute()
GaibuAPI3::execute()
GaibuAPI4::execute()

```

- 動作確認

- エラーハンドリング


```ruby
begin
  GaibuAPI1::execute()
  GaibuAPI2::execute()
  GaibuAPI3::execute()
  GaibuAPI4::execute()
rescue GaibuAPI1Error => exception
  # TOTO
rescue GaibuAPI2Error => exception
  # TOTO
rescue GaibuAPI3Error => exception
  # TOTO
rescue GaibuAPI4Error => exception
  # TOTO
ensure
  # TODO
end
 
```

---

# Rustでは
- 関数の結果は結果とエラーをResultに返します。https://doc.rust-lang.org/std/error/trait.Error.html
- 処理を書くときに、エラーのハンドリングを定義しないとコンパイラーエラーが発生しますので、同時に考えないといけません。

```rust 
use std::fs::File;

fn main() {
    let f: u32 = File::open("hello.txt");
}
```

```
   Compiling error-handling v0.1.0 (file:///projects/error-handling)
error[E0308]: mismatched types
 --> src/main.rs:4:18
  |
4 |     let f: u32 = File::open("hello.txt");
  |            ---   ^^^^^^^^^^^^^^^^^^^^^^^ expected `u32`, found enum `Result`
  |            |
  |            expected due to this
  |
  = note: expected type `u32`
             found enum `Result<File, std::io::Error>`

```


```rust
use std::fs::File;

fn main() {
    let f = File::open("hello.txt");

    let f = match f {
        Ok(file) => file,
        Err(error) => panic!("Problem opening the file: {:?}", error),
    };
}

```

---

# ライブラリーに対すす

## Ruby
- https://rubygems.org/
- Gem / Bundle 

---

## Rust
- https://doc.rust-lang.org/cargo/
- Cargo

---

# コード実行

## Ruby
- rubyインストールしたら、コードを実行できます。
- サーバーで動くために、rubyコードがないといけません
- PHP / Javascriptと同じ

---

## Rust
- rustインストール必要
- コード直接に実行できず、コードをビルドしないといけません
- サーバーで動くのはrustコードが必要じゃなく、ビルドしたファイルだけで十分です。

---

# 最後に
- rustを書くときに、rubyと似てるものはあります。
- rubyの考えり方でそのまま持ってRustに行かないで、考えりを少し変えないといけません。