2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

RustとRubyの違い

Posted at
1 / 34

RustとRubyの違い


Mut


  • Ruby: 変数は値変えられます
hoge = 1
hoge = 2
p hoge

# 結果: => 2

  • Rust: 変数は値変更不可(immutable)
fn main() {
  let hoge = 1;
  hoge = 2;
  
  <!-- 
    ビルドエラー 
    error[E0384]: cannot assign twice to immutable variable `hoge` 
  -->
  
  
  println!("Hoge {:}", hoge);
}


  • Rust: 変数の値変更したい場合、mutを付けないといけません
fn main() {
  let mut hoge = 1;
  hoge = 2;
  
  println!("Hoge {:}", hoge);
  <!-- 結果: Hoge 2 -->
}


  • Ruby: 変数の型がありません、コンパイラーは値から型を付けます (PHPなどと同じ)
hoge = "as"
a.class
# => String

hoge = 12
hoge.class
# => Integer

  • Rust: 変数の型は変更出来ません、(C, Java, Cotlin, Swiftなどと同じ)
fn main() {
  let mut hoge = 1; 
  <!-- Hoge変数は `&str` 型になります-->

  hoge = "hola";
  // ビルドエラー 
  // error[E0308]: mismatched types
  //  |
  //  |     hoge = "hola";
  //  |            ^^^^^^ expected integer, found `&str`
  
  println!("Hoge {:}", hoge);
}


変数のReference


  • Rustはreferenceがあります。(Cと同じ)
fn main() {

  let a: u8 = 10;
  let b = &a;
  println!("Pointer a: {:p}", b);
  println!("Value   a: {}", a);
  println!("Value   b: {}", b);
}
  
  // Pointer a: 0x7ffd469b821f
  // Value   a: 10
  // Value   b: 10
}

  • Ruby: 全部はobjectなので、変数はPointerです。Rustの書き方が存在しません
a = 12
b = &a

# コンパイラーエラー
# SyntaxError ((irb):23: syntax error, unexpected &)

  • RubyのReference
class Hoge attr_accessor :name end
hoge = Hoge.new
fuga = hoge

hoge.name = "hoge"
p fuga.name
# 結果
# => "hoge"

fuga.name = "fuga"
p hoge.name
# 結果
# => "fuga"


質問1

fn main() {

  let mut a: u8 = 10;
  let b = &mut a;
  
  a = 11;
  println!("Value a: {:}", a);
}

→ エラーがありますか?


質問1の答え

  • エラーはありません

質問2

fn main() {

  let mut a: u8 = 10;
  let b = &mut a;
  
  a = 11;
  println!("Value b: {:}", b);
}

→ 結果はどうなりますか?


質問2の答え

  • エラー発生します
 --> src/main.rs:7:3
  |
7 |   a = 11;
  |   ^
  |
  = note: `#[warn(unused_assignments)]` on by default
  = help: maybe it is overwritten before being read?

error[E0506]: cannot assign to `a` because it is borrowed
 --> src/main.rs:7:3
  |
5 |   let b = &mut a;
  |           ------ borrow of `a` occurs here
6 |   
7 |   a = 11;
  |   ^^^^^^ assignment to borrowed `a` occurs here
8 |   println!("Value b: {:}", b);
  |                            - borrow later used here

error: aborting due to previous error; 1 warning emitted


Borrowing と Ownership


  • Rubyでオーナーとういう概念がない、複数変数はひとつのデータに参照するときに、どの変数でもデータ変更できます
class Hoge attr_accessor :name end
hoge = Hoge.new
fuga = hoge

hoge.name = "hoge"
p fuga.name
# 結果
# => "hoge"

fuga.name = "fuga"
p hoge.name
# 結果
# => "fuga"


  • Rust: 一つの変数だけデータ変更できます。
struct Hoge {
    count: i32,
}
fn main() {
    let mut hoge = Hoge {count: 1};
    let fuga = &mut hoge;
    fuga.count = 2;
    println!("Hoge count: {:}", hoge.count);
    hoge.count = 3;
    println!("Hoge count: {:}", fuga.count);

    //     error[E0502]: cannot borrow `hoge.count` as immutable because it is also borrowed as mutable
    //   --> src/main.rs:8:33
    //    |
    // 6  |     let fuga = &mut hoge;
    //    |                --------- mutable borrow occurs here
    // 7  |     fuga.count = 2;
    // 8  |     println!("Hoge count: {:}", hoge.count);
    //    |                                 ^^^^^^^^^^ immutable borrow occurs here
    // 9  |     hoge.count = 3;
    // 10 |     println!("Hoge count: {:}", fuga.count);
    //    |                                 ---------- mutable borrow later used here

    // error[E0506]: cannot assign to `hoge.count` because it is borrowed
    //   --> src/main.rs:9:5
    //    |
    // 6  |     let fuga = &mut hoge;
    //    |                --------- borrow of `hoge.count` occurs here
    // ...
    // 9  |     hoge.count = 3;
    //    |     ^^^^^^^^^^^^^^ assignment to borrowed `hoge.count` occurs here
    // 10 |     println!("Hoge count: {:}", fuga.count);
    //    |                                 ---------- borrow later used here
}


Nil vs Option


  • Ruby: どの変数でもnil付けられます
  x = 2;
  y = nil;
    
  print "x: #{x}, y: #{y}"
  # 結果
  # x: 2, y: => nil

  • Rust: nilは存在しません → 代わりにデータがある・ないの型があります → Option

fn main() {
    let x: Option<u32> = Some(2);
    let y: Option<u32> = None;
    
    println!("x: {:?}, y: {:?}", x, y)
}


  • Rust OptionのNone = Rubyのnil
  • RUst OptionのSome = RUbyのnilじゃない

  • Ruby: Nilに関連するoperatorがありません
a = nil
b = a + 1
# NoMethodError (undefined method `+' for nil:NilClass)

  • Rust: Optionに関連するoperatorもありません、ただOptionのデータで使うとときに、Noneをチェックしないといけません → 安全です
fn main() {
  let a: Option<u32> = Some(2);

  let value = match a {
    Some(v) => v,
    None => 0 
  };

  let b = value + 1;
  
  println!("b: {:}", b);
}

Result - エラーハンドリング


  • エラーは外部APIまたは特別な処理の時に、エラー発生します。

例: FbApiError, ValidationError..


  • Ruby: 関数開発の時にエラー気にしなくも開発出来ます

def call_api(endpoint, method)
   fb_client.call(endpoint, method) # エラーがある処理
   
   'API Done'
end


  • Ruby: エラーハンドリングの時に開発者に決められます。

def call_api(endpoint, method)
  begin
    fb_client.call(endpoint, method)
  rescue => exception
    'API ERROR'
  end

  'API Done'
end


  • Ruby: エラーハンドリングしないと関数が呼ばれるところにエラー投げます。
def call_api(endpoint, method)
   fb_client.call(endpoint, method) # エラーがある処理
   
   'API Done'
end

call_api("me", "GET") # fb_client.call でエラー発生したら、ここに止まります。

  • Rust: 関数開発の時にエラーがあれば、Resultとうい型になります。
    pub async fn call_api(&self, endpoint: &str, method: &str) -> String{
        self.call(endpoint, method) // エラーがある処理

        "API DONE".to_owned()
    }

  • Rust: Resultをみるとエラーがあるかどうか分かります。
    pub async fn call_api(&self, endpoint: &str, method: &str) -> String{
        return match self.call(endpoint, method) {
             Ok(value) => "API DONE".to_owned(),
             Err(error) => "API ERROR".to_owned()
        }
    }


  • Rust: エラーハンドリングしないときに、エラー発生したら何も起こらない
    pub async fn call_api(&self, endpoint: &str, method: &str) -> String{
        await self.call(endpoint, method) // エラーがある処理

        "API DONE".to_owned()
    }

    pub async fn run(&self){
        await self.call_api("me", "GET") // .call でエラー発生しても、何も起こらない
    }

まとめ

  • Mut
  • Reference
  • Nil/Option
  • Result
2
0
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
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?