Open18

Rustの勉強を始める

Y8Y8

dbg!()

  • デバッグに便利なマクロ
  • 式と結果が標準エラーを出力
  • println!などのマクロと違ってそのまま式が出力され、出力後に値を返す点が異なる
Y8Y8

プロジェクトの作り方

cargo new PRJ
Y8Y8

コンパイル & 実行

cargo run
Y8Y8

コメントの書き方

  • //! ... inner line (行末までがコメント。 // と同様)
  • /*! ... */ inner block (囲まれた範囲内がコメント。 /* ... */ と同様)
  • /// ... outer line
  • /** ... */ outer block
Y8Y8

演算子!とは?

マクロ展開

(付録B:演算子と記号 - The Rust Programming Language 日本語版)

  • マクロとは

マクロ
本全体を通じてprintln!のようなマクロを使用してきましたが、マクロがなんなのかや、 どう動いているのかということは完全には探究していませんでした。 Rustにおいて、マクロという用語はある機能の集合のことを指します:macro_rules!を使った 宣言的 (declarative) マクロと、3種類の 手続き的 (procedural) マクロ:

  • 構造体とenumにderive属性を使ったときに追加されるコードを指定する、カスタムの#[derive]マクロ
    • 任意の要素に使えるカスタムの属性を定義する、属性風のマクロ
Y8Y8

for / while / loop

  • while: 条件を満たすまで計算をし続ける
use rand::Rng;

fn main() {

    let mut num_loop = 0;
    let mut num_add = 0;

    while num_add < 6 {
        let x = rand::rng().random_range(0..100);
        num_loop += 1;
        println!("loop No.{}", num_loop);

        if x > 50 {
            println!("乱数が50より大きいので1足します");
            num_add += 1;

            if num_add >= 6 {
                println!("5に到達したので、break します");
                break; //exit from loop
            }
        } else {
            println!("乱数が50以下なのでそのままの値です -> {}", num_add);
        }

    }

}
Y8Y8

多重break

ループが入れ子になっている場合、内側のループだけでなく、外側のループからも一気に脱出したいときは下記のようなコードでかける

'soto: for i in 1..=3 { // 外側のfor ループに 'sotoという名前をつける
    for j in 1..=3 {
        if i * j == 8 {
            println!("外側まで一気に脱出");
            break 'soto // 'sotoの外側に脱出
        }
    }
}
Y8Y8

match構文

match 数字 {
    パターン1 => {
        // run
    },
    パターン2 => {
        // run
    },
    _ => {
        // それ以外
    }
}
use rand::Rng;

fn main() {

    let switch_no = rand::rng().random_range(1..=2);

    match switch_no {

        1 => {
            println!("match 1");
        },
        2 => {
            println!("match 2");
        },
        _ => unreachable!(),
    }

}

Y8Y8

列挙型と構造体

  • 列挙型 / Enumerated type: あらかじめ定義された値のみ取りうる型
eunm 型名 {
    列挙子1,
    列挙子2
}

let a = 型名::列挙子で変数を付与できる

Y8Y8
  • 構造体 / : 複数の変数をまとめて管理することができるデータ構造。
struct NAME {
    name1: 変数,
    name2: 変数2,
}
Y8Y8

println!()

fn main() {

    let a = [1, 2, 3];
    println!("a = {}", a);
    
}
// }", a);
// ^ `[{integer}; 3]` cannot be formatted with the default formatter

というコンパイルエラーが出てしまう。

fn main() {

    let a = [1, 2, 3];
    println!("a = {:?}", a);
    
}

のように:?を加えるとOK

in format strings you may be able to use {:?}

Y8Y8

rustでvectorに値を追加する

fn main() {

    let mut a = [1, 2, 3];
    a.push([4]);
    println!("a = {:?}", a);

}

はエラー

fn main() {

    let mut a = vec![1, 2, 3];
    a.push(4);
    println!("a = {:?}", a);

}

のように、vec!マクロでベクター指定

Y8Y8

rustでvectorいろいろ

fn main() {

    let mut a = vec![3, 5, 7];
    // 末尾に追加 pop
    a.push(6);
    println!("a = {:?}", a);
    println!("length = {}", a.len());
    
    // 任意の位置に追加 insert
    a.insert(0, 1);
    println!("a = {:?}", a);

    a.insert(2, 1);
    println!("a = {:?}", a);
    
    // 末尾を削除して Option<T>で返す
    let b = a.pop();
    println!("b = {:?}", b);
    println!("a = {:?}", a);
    
    // 指定した位置を削除 remove
    a.remove(2);
    println!("a = {:?}", a);

}

// a = [3, 5, 7, 6]
// length = 4
// a = [1, 3, 5, 7, 6]
// a = [1, 3, 1, 5, 7, 6]
// b = Some(6)
// a = [1, 3, 1, 5, 7]
// a = [1, 3, 5, 7]
Y8Y8

loopとrangeに関して

fn main() {
    for n in 1..3 {
        println!("loop range:1..3 n is {}", n)
    }
    for n in 1..=3 {
        println!("loop range:1..=3 n is {}", n)
    }
    for n in 0..=3 {
        println!("loop range:0..=3 n is {}", n)
    }

    let set = vec!["a", "b", "c"];
    for i in set.iter() {
        println!("loop range:set.iter() {}", i);
    }
    
}
Y8Y8

関数

fn FNNAME() -> 戻り値の型 {
    // 処理,,,
}

Y8Y8

ブロック式


fn main() {
    let some_val: i32 = {
        let tmp = 2;
        tmp
    }

}
  • {で囲われたコードブロックもrustでは式として処理
  • 最後の式の値が使われる。 ;は書かない点に注意
  • 変数tmpはこのコードブロックの中のみで有効。この外側では使えない