- 以下のページで学習を開始
- Rust は rustup と rust-analyzer を homebrew でインストール
- bootstrap で .cargo フォルダがないことを確認の上で rustup-init を実行
- vscode の Rust 機能拡張を追加
- 単一ファイルの記述
- rustc でコンパイルして実行。これは cc と変わらない
- でも実際のプロジェクトはこんな簡単ではないので、cargo を使う。ビルドツールであり、環境依存マネージャーでもあるとのこと。cargo new でプロジェクトを作成
- 設定などは Cargo.toml で記述。toml ファイルは vim 以来か。cargo run でプログラム実行
- 関数について。関数は fn で記述。Ruby の def と同じ感じ。行は ; で終わるが、終わらない時は次の行を 4 インデントする。このあたりはフォーマッタがなんとかしてくれると信じる
- println! はマクロ。{} は C 言語の %s みたいな感じ。数字などが渡されても文字列変換メソッドが入るので、型を区別しなくていいということ。
- {} を書きたい時にはどうするんだろう。と思って色々やってみたが、これでいいのかな。\{\}ではなかった。
- 変数について。変数は let で設定。変数は不変(immutable)なので再代入は不可。
- 可変(mutable)にしたければ mut を付ける。デフォルトではないということは滅多には使わない感じか。後で出てくる構造体の一部だけ変更するような時に使うくらいではないかとのこと。
- 変数のシャドウ処理。mut だといつでも変更可能になってしまうので、シャドウ処理で同じ変数名を付けることができる。これだとあまり意味がないが、スコープが変わると意味があるかも。
- 型推論は自動で行われるが、自分で型を指定することもできる。
u32
は符号なし32ビット整数
- 型を指定しているのに違うものを入れるとコンパイル時点でエラーになる。静的にエラーになるのは嬉しい。
- 整数型
- i8, i16, i32, i64, isize が符号あり
- u8, u16, u32, u64, usize が符号なし
- 型推論できない時は i32
- 浮動小数点型
- f32 と f64。デフォルトは f64
- ブール値
- true または false。条件式を実行すると true か false が生成される
- 文字
- '' で括ると文字
- 内部は 21ビットの Unicode code (UTF-8 ではない)
- 文字列1 (str 型)
- "" で括ると文字列。文字列リテラルなどで長さが既知
- 参照する場合には &str になる。& は参照を示す
- 文字列2 (String 型)
- 長さがわかっていない場合。作り方は後で出てくると思う
- タプル
- 表記は Swift と同じ。
- タプルの長さは固定。作成時に決定
- 中身はなんでも良い。下の例では文字列、数値、ブーリアン値が入っている
- if は条件式を記述。Ruby のように式には () はいらない
- Ruby と同じく if 自体が値を返すので、C の三項演算子のように使える。let の文になるので最後にセミコロンが必要。Ruby だと「;」がいらないので気にならないが、Rust だと「};」の形になることに注意。
- 複数の条件分岐は else if となる。
- 構造体の種類は3種類
- 従来の構造体: key-value 形式。Ruby の Hash に近いイメージだが、定義した時以上にキーは増えない
- タプル構造体: 中身はタプルでキーはない。要素の並びが固定化されたタプルの雛形
- ユニット構造体: ここでは説明がないので、後で出てきた時に確認
- 構造体の命名規則
- Ruby の Class 名のように大文字で始める
- 従来の構造体
- 定義方法(従来の構造体)
- key-value をあらかじめ宣言する。要素はフィールドと呼ぶとのこと
- 他の二つと違って、最後に「;」を書かないとのこと。これは間違えそうなので注意。
- 構造体の作成(従来の構造体)
- 作り方は構造体名を記述後に、Ruby の Hash と同じ形式で記載する。
- name は String なので、"" の str 型は入れられない。String::from で str 型から String 型に変換するようだ
- 構造体の利用方法(従来の構造体)
- 構造体のフィールドへのアクセスは C 言語と同じく、.フィールド名と書けばよい
- タプル構造体
- 定義方法(タプル構造体)
- タプルには名前がないので、定義時には型だけを並べる
- 通常の構造体と異なり、「;」は必要
- 構造体の作成(タプル構造体)
- タプル構造体は構造体名の後にタプルの生成が入る。
- 通常のタプルとの違いは型の並びが固定化されていること
- 構造体の利用方法(タプル構造体)
- タプルの要素には.1, .2 のように要素番号を記述する。
- 列挙型
- 列挙型について
- C 言語の列挙型とは全く意味が違う。
- elm のカスタム型と同じで、複数のバリアントを同じ枠にハメるための仕組み
- 静的型付けが必要なため、多様性が必要な入力などを取りまとめるために利用
- 列挙型の定義
- 以下の例では WebEvent という列挙型を定義している
- ここでは、
WELoad
,WEKeys
,WEClick
という三つのバリアントをまとめている WELoad
はまだ説明されていないユニット構造体、WEKeys
はタプル構造体、WEClick
は従来の構造体。それぞれは匿名構造体- 列挙型を受け付ける場合には、全てに対して処理を受け付けるようにしなければならない
- 構造体による列挙型定義
- 匿名構造体で処理するのは面倒なので、定義された構造体を使って列挙型を作る方がよいらしい
- 列挙型のインスタンス化
- 単純なバリアント。boolean の引数だけを一つもつ場合
- 通常の構造体を引数に持つバリアント。x, y = (100, 250) を持つ MouseClick 構造体を受け付ける
- タプル構造体を引数に持つバリアント。String 型と char のタプルを持つ KeyPress 構造体を受け付ける
- 提示されているサンプルプログラムの表示部分
- {:#?}を使っている。ただしこのままでは動作しない
- {:#?}を使うためには、その構造体や列挙型の前に
#[derive(Debug)]
を付ける必要がある。
- 関数の基本
- Rust の関数は fn で始まる。Ruby の def と同じイメージで。ただし、関数のスコープは {}。引数なしでも () は必要の様子。
- 関数の入力引数
- 引数は変数名の後ろに型を書く。Swift と同じ形だが、Swift や Objective-C のようにラベルはつけない。Swift の _ 付きのような感じ。今は IDE やエディタのサポートがあるので、ラベルがなくてもミスらないということか。
- 関数の戻り値
- 関数の戻り値は Swift と同じ形で関数名の後ろに
->
で型を記述する。 - 値を途中で返すときには、return 文を使うことができる。これはステートメントなので「;」が必要
- Ruby と同じで最後に評価した式も返り値にになる。これはステートメントでないので、「;」をつけてはいけない。
- デフォルトは最後に式を書く形だと思われる。
- 演習の解説は省略
- 演習結果はこんな感じになりました。PartialEq だけがまだ説明がないですね。
- 配列
- 配列の定義は2種類
- コンマ区切りで要素を並べる
- 初期値と配列の長さで指定
- 配列は[T; size]という形で内部に保存される
- 配列の要素の方は T で固定。Ruby などと違ってどんな型が入ってもいいわけでない
- 配列のサイズも size で固定。可変長ではない
- 配列のインデックス
- 配列の要素は他の言語と同様に 0 から始まる。特に問題はなし
- 範囲外のアクセスについて、コンパイラが判断できる場合にはコンパイルエラーになる
- ベクター (翻訳の表記が揺れているがベクターにしておく)
- ベクターの概念
- 配列は固定長だが、ベクターは可変長
<vector>u32
、<vector>String
のように作成する- 型がわかっていない場合には、
<vector><T>
のようにジェネリック(未知)データ型で定義できる - マクロを使ったベクターの初期化
- vec! というマクロを使って、配列からベクターを作成できる
- Vector::new() による初期化
- new() メソッドで空のベクターが作成できる
- 要素の追加などをしたい場合は、mut にする必要がある
- プッシュとポップ
- push(<value>) を使って一番後ろに値を追加できる。
- ジェネリックで作成した場合、最初に push した値で型が確定
- 以降は同じ型のものしか入れられない
- pop() を使って値を取り出せる
- 取り出すのも後ろから。
- push, pop なので FILO バッファになる
- ベクターのインデックス
- 要素アクセスは配列と同じ
- 範囲外アクセスした場合には、パニックが発生
- ハッシュマップ
- ハッシュマップの作成
- HashMap<K, V> の形式
- ベクターと同様に拡大可能
- use で HashMap を入れる必要あり
- key, value を追加できるようにするには mut を付ける
- Hash は .insert で key, value を追加
- toString() は String の実態を作成するメソッド。Hash が実態を所有する必要があるため
- 値の取得
- get() で値を取得できる
- get の引数は参照文字列(&str)で良いので、直接 "Programming in Rust" でもよい
- この例ではそのことを理解させるために、book という変数に入れている(型は &str)
- get の返り値は取得できない場合もあるので、Optional になるとのこと。
- Rust では Some(中身) という形になるらしい
- Optional の外し方はまだ説明はない
- 値の削除
- remove() で値を削除できる
- 削除したものを get すると None になる
- Rust のループは3つ
- loop: 無限ループ
- whlie: 条件が true の間ループ
- for: コレクションを順にループ
- loop
- break まで止まらない
- loop 自体も値を返せる
- break の後に返す値を示せる
- break が複数ある場合には、全てが同じ型でないとエラーになる
- 値が明示的に返されなかった場合には、空のタプルが返却される
- while
- 条件を満足する間ループする
次のページはこちらRust 学習記録(2)