mimikakimemo

自分用メモ。

Rust に付け焼き刃で入門する 2

Rust に付け焼き刃で入門する 1 の続き。

3. 一般的なプログラミングの概念

3.1. 変数と可変性

変数と可変性 - The Rust Programming Language 日本語版

不変のメリットについての説明は、特に Rust に限ったことではない。

不変な変数とは別に、定数もある。型注釈は必須。

const MAX_POINTS: u32 = 100_000;

シャドーイングについては、前回見たとおり。

3.2 データ型

データ型 - The Rust Programming Language 日本語版

Rust は静的型付き言語。型推論してくれるので、型注釈は必要なところでだけで良い。

整数型や論理値型など、プリミティブな型はスカラー型と呼ぶ。整数にはサイズがある。ローレベルな感じ。迷ったら Rust のデフォルトである i32 型を使えば良いとのこと(最速なので)。浮動小数点型の方は f64。いわゆる double。演算子は普通な感じ。

bool 型は truefalse

char 型は Unicode スカラー値の一つ。'a' のようにシングルクォートで囲む。文字列 "a" とは別。

タプルの要素の型は一致しなくてよい。destructring も可能。要素には、x.0 のようにドットでアクセス。

配列 array は同じ型の要素からなり、固定長。他の言語でいうような可変長のリストは、ベクタ vector を使う。配列の要素には x[0] のようにしてアクセス。範囲外へのアクセスは実行時エラー panic になる。

3.3 関数

関数 - The Rust Programming Language 日本語版

ソースコード中でanother_functionmain関数の後に定義していることに注目してください; 勿論、main関数の前に定義することもできます。コンパイラは、関数がどこで定義されているかは気にしません。 どこかで定義されていることのみ気にします。

なるほど。JavaScript だと巻き上げ hoisting が起きるけど、Rust はどうなんだろう。

fn main() {
    println!("Hello, world!");
    another_function();
}

let num = 42;

fn another_function() {
    println!("{}", num);
}

これだとerror: expected item, found keyword `let` というエラーになった。そもそもここには let を置けないので、let と関数定義の順序を気にする必要はない様子。また、

fn main() {
    println!("Hello, world!");
    another_function();

    let num = 42;

    fn another_function() {
        println!("{}", num);
    }
}

can't capture dynamic environment in a fn item というエラーになった。関数定義の順序を気にしないといけないようなコードは、そもそも文法的に許されていないようだ。

関数シグニチャにおいて、各仮引数の型を宣言しなければなりません。

はい。

文とは、なんらかの動作をして値を返さない命令です。 式は結果値に評価されます。

変数宣言や関数定義は文。プロック {} は式。式にセミコロンをつけると文になる。

戻り値に名前を付けはしませんが、 矢印(->)の後に型を書いて確かに宣言します。Rustでは、関数の戻り値は、関数本体ブロックの最後の式の値と同義です。 returnキーワードで関数から早期リターンし、値を指定することもできますが、多くの関数は最後の式を暗黙的に返します。

Rust では、ブロックの最後の式の値を戻り値とみなす。式なのでセミコロンはつけない(つけると文になってしまう)。慣れるまではうっかりセミコロンを消したり、つけたりしてしまいそうだ。ただ、戻り値の型が食い違っていたらコンパイルエラーで気づけるので、そこまで神経質にならなくても良さそう。

戻り値なしの場合は空のタプル -> () で型を表現できるが、この場合に限って、戻り値の型注釈を省略できるっぽい。

3.4. コメント

// でコメントを書ける。

3.5. フロー制御

フロー制御 - The Rust Programming Language 日本語版

if は式なので、値を返す。条件は bool 型である必要がある。アームの {} は省略不可。else, else if も使えるが、各アームが返す型は同じでなければならない。ユニオン型にはなってくれないようだ。

各アームが返す型は同じでなければならないので、値を返す式として使う場合は else が必ず必要。

let a = if cond { 100 } else { 0 }; // OK
let a = if cond { 100 }; // NG

無限ループは loop。条件付きループは while。コレクション(イテレータ?)に対するループは for ... inbreakcontinue もある。このあたりは普通な感じ。

ループは式なんだろうか? break から値は返せるんだろうか? …特にこのページには記述がなかった。