LoginSignup
5
1

More than 1 year has passed since last update.

RubyからRustに移行について

Posted at
1 / 18

RubyのエンジニアはRustの最初に困ったこと

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

現在

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

Class/def VS Struct / impl

Rubyでは

  • Class / def
  • データを持つ
  • 処理を定義する
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を使います
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

  • 処理は別で定義出来ます
module Cream
  def cream
    puts "Hello Qiita User"
  end
end

class Cookie
  include Cream
end

cookie = Cookie.new
cookie.cream

RustのTrait

  • 処理も別で定義出来ます
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は明確の定義ががありません。

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


結果

Integer
String

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

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

error[E0308]: mismatched types


つまり

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

Result/Error の考えり

Rubyでは

  • ロジックを集中にして、動作確認して、そのあとにエラーハンドリングをやります。

処理開発


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

  • 動作確認

  • エラーハンドリング

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
  • 処理を書くときに、エラーのハンドリングを定義しないとコンパイラーエラーが発生しますので、同時に考えないといけません。
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>`

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


Rust


コード実行

Ruby

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

Rust

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

最後に

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

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1