🦞

Tour of Rust の個人的文法まとめ

2024/04/20に公開

はじめに

Tour of Rust 日本語版 をやってみて、Rustのコーディング規則や知らなかった知識などをまとめていきます。
基本的に自分が見返す用なので、網羅性についてはご容赦ください。

1章 - 基礎

変数

  • 宣言時はletを使用
  • 型推論可能
  • 型指定可能 (データ型一覧)
      // x の型を指定
      let x: f64 = 3.14159;
      println!("{}", x);
    
  • 変数名はスネークケース

変数の変更

  • 可変(再代入可能)な変数には mut を使用
fn main() {
    let mut x = 42;
    println!("{}", x);
    x = 13;
    println!("{}", x);
}

// => 42
// => 13

基本的な型

  • ブール型
    • true, false
  • 符号なし整数型
    • u8, u32, u64, u128
  • 符号あり整数型
    • i8, i32, i64, i128
  • ポインタサイズ整数型
    • usize, isize
    • メモリ内のインデックスとサイズを表す
  • 浮動小数点型
    • f32, f64

数値型は、数値の最後に型を付加することでも型指定可能

let a = 12u8;
let c = 4.3f32;

基本型の変換

  • 数値型の型変換では型を明示する
    • asを用いることで型変換可能
fn main() {
    let a = 13u8;
    let b = 7u32;
    let c = a as u32 + b;
    println!("{}", c);

    let t = true;
    println!("{}", t as u8);
}

// => 20
// => 1

定数

  • 宣言時はconstを使用
  • 明示的な型指定が必要
  • 定数名は大文字のスネークケース(SCREAMING_SNAKE_CASE)
const PI: f32 = 3.14159;

fn main() {
    println!(
        "ゼロからアップル {} を作るには、まず宇宙を創造する必要があります。",
        PI
    );
}

// => ゼロからアップル 3.14159 を作るには、まず宇宙を創造する必要があります。

配列

  • データ型は [T; N]
    • T : 要素の型
    • N : コンパイル時に決定される固定長(要素数)
  • array[x] で要素取得可能
    • x は usize型のインデックスである
fn main() {
    let nums: [i32; 3] = [1, 2, 3];
    println!("{:?}", nums);
    println!("{}", nums[1]);
}

// => [1, 2, 3]
// => 2

関数

  • 戻り値の型は矢印の後に書く
  • 戻り値は最後の式を暗黙的に返す(rubyと同じ)
  • 関数名はスネークケース
fn add(x: i32, y: i32) -> i32 {
    return x + y;
}

fn main() {
    println!("{}", add(42, 13));
}

// => 55

複数の戻り値

  • 戻り値をタプルで返すことで複数の値を返すことが可能
fn swap(x: i32, y: i32) -> (i32, i32) {
    return (y, x);
}

fn main() {
    // 戻り値をタプルで返す
    let result = swap(123, 321);
    println!("{} {}", result.0, result.1);

    // タプルを2つの変数に分解
    let (a, b) = swap(result.0, result.1);
    println!("{} {}", a, b);
}

// => 321 123
// => 123 321

空の戻り値

  • 戻り値の型が指定されていない場合、空のタプル(unit)を返す

2章 - 基本制御フロー

if/else if/else

  • よくある条件分岐
fn main() {
    let x = 42;
    if x < 42 {
        println!("42 より小さい");
    } else if x == 42 {
        println!("42 に等しい");
    } else {
        println!("42 より大きい");
    }
}

// => 42に等しい

loop

  • よくあるループ
fn main() {
    let mut x = 0;
    loop {
        x += 1;
        if x == 42 {
            break;
        }
    }
    println!("{}", x);
}

// => 42
  • breakで値を返すことも可能
fn main() {
    let mut x = 0;
    let v = loop {
        x += 1;
        if x == 13 {
            break "13 を発見";
        }
    };
    println!("loop の戻り値: {}", v);
}

// => loop の戻り値: 13 を発見

while

  • 条件付きのループ
fn main() {
    let mut x = 0;
    while x != 42 {
        x += 1;
    }
}

for

  • イテレータとして評価式を反復
  • .. 演算子は開始番号から終了番号の手前までの数値を生成する
  • ..= 演算子は開始番号から終了番号までの数値を生成する
fn main() {
    for x in 0..5 {
        println!("{}", x);
    }

    for x in 0..=5 {
        println!("{}", x);
    }
}

// => 0
// => 1
// => 2
// => 3
// => 4
// => 0
// => 1
// => 2
// => 3
// => 4
// => 5

match

  • 値の取り得る全ての条件を評価し、真である場合のコードを実行する
  • switch文と同等
fn main() {
    let x = 42;

    match x {
        0 => {
            println!("found zero");
        }
        // 複数の値にマッチ
        1 | 2 => {
            println!("found 1 or 2!");
        }
        // 範囲にマッチ
        3..=9 => {
            println!("found a number 3 to 9 inclusively");
        }
        // マッチした数字を変数に束縛(バインディング)
        matched_num @ 10..=100 => {
            println!("found {} number between 10 to 100!", matched_num);
        }
        // どのパターンにもマッチしない場合のデフォルトマッチが必須
        _ => {
            println!("found something else!");
        }
    }
}

// => found 42 number between 10 to 100!

ブロックから式を返す

  • if, match, 関数, ブロックは;つけない式であれば戻り値として使用される
fn example() -> i32 {
    let x = 42;
    // Rust の三項式
    let v = if x < 42 { -1 } else { 1 };
    println!("if より: {}", v);

    let food = "ハンバーガー";
    let result = match food {
        "ホットドッグ" => "ホットドッグです",
        // 単一の式で値を返す場合、中括弧は省略可能
        _ => "ホットドッグではありません",
    };
    println!("食品の識別: {}", result);

    let v = {
        // ブロックのスコープは関数のスコープから分離されている
        let a = 1;
        let b = 2;
        a + b
    };
    println!("ブロックより: {}", v);

    // Rust で関数の最後から値を返す慣用的な方法
    v + 4
}

fn main() {
    println!("関数より: {}", example());
}

// => if より: 1
// => 食品の識別: ホットドッグではありません
// => ブロックより: 3
// => 関数より: 7

Discussion