S-JIS[2024-09-16/2024-12-19] 変更履歴

Rustステートメント

Rustの文のメモ。

  • mod(モジュールの宣言)
  • use(モジュールのインポート)
  • fn(関数定義)[/2024-12-19]

概要

Rustのifやmatch・ループは文として使うことも出来るが、式として値を返すことも出来る。

ifやwhile等の条件式の部分は、C言語やJavaだと丸括弧で囲むが、Rustでは丸括弧で囲まない。
条件式と処理本体との境界をはっきりさせる為に、処理本体は必ず波括弧で囲む。波括弧抜きでひとつの文だけを書くことは出来ない。


ブロック

波括弧で囲んで複数の文を書ける。
ブロックがローカル変数のスコープ(変数が存在できる範囲)となる。

{
    文;
〜
    文;
}

波括弧内の最後の式の値がブロックの値になる。
この場合、最後の式の末尾にセミコロン「;」を付けてはいけない。
(セミコロンを付けると、ブロックの値は()ユニット型の唯一の値)になる)

{
    文;
〜
    文;
    式
}

ブロックの例

    let n = {
        let a = 1;
        let b = 2;
        a + b	// ブロックの値(末尾にセミコロンを付けない)
    };
    println!("n = {}", n);

if

if 条件式 {
    〜
}〔else if 条件式 {
    〜
} 〕〔else {
    〜
} 〕

if let


ifの例

    if n % 15 == 0 {
        println!("{} FizzBuzz", n);
    } else if n % 3 == 0 {
        println!("{} Fizz", n);
    } else if n % 5 == 0 {
        println!("{} Buzz", n);
    } else {
        println!("{}", n);
    }
    let s = if n % 15 == 0 {
        String::from("FizzBuzz")
    } else if n % 3 == 0 {
        String::from("Fizz")
    } else if n % 5 == 0 {
        String::from("Buzz")
    } else {
        n.to_string()
    };	// このセミコロンは、letの末尾
    println!("{} {}", n, s);

match

match 値 {
    パターン1 => 処理1,
    パターン2 => 処理2,
    パターン3 => {
       〜
    } // 波括弧でブロックを作った場合は、末尾カンマは不要
    …
}

複数の「パターン => 処理」はカンマで区切る。最後の処理の末尾にカンマがあっても無視される。
それぞれの「パターン => 処理」が別々のスコープを持つ。(異なるパターンにおいて同名の変数を使うことが出来る)
(Javaのswitchだと、switchブロックがひとつのスコープになり、異なるcaseで同名の変数を宣言することは出来ない)

処理に複数の文を書きたい場合は波括弧で囲んでブロックにする。
その際は、ブロックの終わりの直後にカンマは不要。

matchでは網羅性チェックが行われる。

パターンの例 説明
ひとつの値。
let n : i32 = 0;
match n {
    0 => "zero",
    〜
}
_ (アンダースコア) 全てにマッチする。
match n {
    〜
    _ => "default",
}
値1 | 値2 | 値3 複数の値。
match n {
    1 | 2 | 3 => "little",
    〜
}
開始..終了 範囲(終了は含まない)。
開始 <= 値 && 値 < 終了
match n {
    1..3 => "little",
    〜
}
開始..=終了 範囲(終了も含む)。
開始 <= 値 && 値 <= 終了
match n {
    1..=3 => "little",
    〜
}
パターンマッチ OptionとかResultとか。
let o : Option<i32> = Some(123);
match o {
    Some(n) => println!("n = {}", n),
    None => println!("none"),
}
パターン if 条件式 ガード条件。
match o {
    Some(n) if n >= 100 => println!("{} large", n),
    Some(n)             => println!("{} small", n),
    None => println!("none"),
}

if let

if letはmatchの特別なケースのようなもの。
「ひとつのパターンにだけ合致すればよく、合致しなかった値に対しては何もしない」ような場合に便利。

if let パターン = 値 {
    〜
}〔else {
    〜
} 〕

if letの例 matchで書いた場合
let o : Option<i32> = Some(123);
if let Some(n) = o {
    println!("n = {}", n);
}
let o : Option<i32> = Some(123);
match o {
    Some(n) => println!("n = {}", n),
    _ => {},
}

Some(n) = o」は、代入形式であり、「==」による比較ではない。
oがパターンSome(n)に合致する場合に限り、処理が実行される。


loop

loopは無限ループ。
breakでループから抜ける。(returnで関数から抜けてもいい)

loop {
    〜
}

breakcontinue


機能的には「while true」と同じだが、loopの方が条件判定しない分だけ速いらしい。


loopの例

    let mut n = 0;
    loop {
        println!("n = {}", n);

        n += 1;
        if n >= 5 {
            break;
        }
    }

while

whileは条件を満たす間ループする。

while 条件式 {
    〜
}

breakcontinue


whileの例

    let mut n = 0;
    while n < 5 {
        println!("n = {}", n);

        n += 1;
    }

for

forはイテレーターの要素を順番に処理する。

for 変数 in イテレーター {
    〜
}

変数を使わない場合は「_」(アンダースコア)にする。

breakcontinue


forの例

説明 Java相当 Scala相当
10回繰り返す(0〜9)
for i in 0..10 {
    println!("{}", i);
}
for (int i = 0; i < 10; i++) {
    System.out.println(i);
}
for (i <- 0 until 10) {
  println(i)
}
1から10まで
for i in 1..=10 {
    println!("{}", i);
}
for (int i = 1; i <= 10; i++) {
    System.out.println(i);
}
for (i <- 1 to 10) {
  println(i)
}
コレクション
let array = [1, 2, 3];
for elem in array {
    println!("{}", elem);
}
final int[] array = { 1, 2, 3 };
for (var elem : array) {
    System.out.println(elem);
}
val array = Array(1, 2, 3)
for (elem <- array) {
  println(elem)
}
変数を使わない場合
for _ in array {
    println!(".");
}
for (var _ : array) {
    System.out.println(".");
}
for (_ <- array) {
  println(".")
}
コレクションのインデックス付き
for (i, elem) in array.iter().enumerate() {
    println!("{}: {}", i, elem);
}
int i = 0;
for (var elem : array) {
    System.out.printf("%d: %d\n", i, elem);
    i++;
}
for ((elem, i) <- array.zipWithIndex) {
  println(s"$i: $elem")
}

break

breakでループ(loopwhilefor)から抜ける。

break 〔'ラベル〕 〔値〕;

ループにラベルを付けてbreakにそのラベルを指定すると、そのループから抜ける。二重ループを抜けるのに便利。
ラベルの命名ルールとして、ラベル名の先頭にアポストロフィー「'」を付ける。(ライフタイムと同じ命名ルール)

breakに値を指定すると、その値がループの戻り値になる。


breakの例

    'loop1: for i in 0..5 {
        for j in 0..3 {
            if i == 3 && j == 1 {
                break 'loop1;
            }
            println!("i={}, j={}", i, j);
        }
    }
    let r = loop {
        〜
        break 123;
    };

continue

continueでループ(loopwhilefor)の先頭に戻る。
(forの場合、次の要素へ移る)

continue 〔'ラベル〕;

ラベルに関してはbreakと同様。


continueの例

    'loop1: for i in 0..5 {
        for j in 0..3 {
            if i == 3 && j == 1 {
                continue 'loop1;
            }
            println!("i={}, j={}", i, j);
        }
    }

Rustへ戻る / 技術メモへ戻る
メールの送信先:ひしだま