HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
📌
hkob's Notion
/Rust 学習記録/
Rust 学習記録(1)

Rust 学習記録(1)

  • 以下のページで学習を開始
Rust の最初のステップ - Learn
利用が広がり人気が高まっている新しいプログラミング言語の習得に関心がありますか? ここから始めましょう。 Rust で高速で効果的なプログラムを構築するために必要な知識の基盤を築きましょう。 このラーニング パスの内容は次のとおりです。 Rust コードの最初の行を記述するために必要なツールをインストールする。 Rust の基本的な概念を学ぶ。 エラーを処理する方法を学ぶ。 Rust でメモリを管理する。 ジェネリック型と特性を使用する。 パッケージとクレート用のモジュールを設定する。 自動テストを記述して実行する。 コマンドライン プログラムを作成する。
Rust の最初のステップ - Learn
https://docs.microsoft.com/ja-jp/learn/paths/rust-first-steps/
  • Rust は rustup と rust-analyzer を homebrew でインストール
  • bootstrap で .cargo フォルダがないことを確認の上で rustup-init を実行
  • vscode の Rust 機能拡張を追加
  • 単一ファイルの記述
  • rustc でコンパイルして実行。これは cc と変わらない
  • でも実際のプロジェクトはこんな簡単ではないので、cargo を使う。ビルドツールであり、環境依存マネージャーでもあるとのこと。cargo new でプロジェクトを作成
  • 設定などは Cargo.toml で記述。toml ファイルは vim 以来か。cargo run でプログラム実行
 
Rust の一般的な概念を理解する - Learn
Rust の基礎を学びます。 変数、データ型、構造体、列挙型、関数、インデックス作成、ハッシュ マップ、およびフロー制御について確認します。 このモジュールでは、次のことを行います。 Rust プログラムの基本構造について説明します。 let ステートメントを使用して、変数に値を代入する。 コードにコメントを付けて、わかりやすくする方法を学ぶ。 Rust 標準ライブラリに存在する基本データ型について確認する。 独自の関数を作成する。 コレクションを使用して、複数の値を 1 つの構造体に格納する。 コードで条件付きステートメントとループを使用する方法を学ぶ。 Rust 開発環境が既にセットアップされていること。 Cargo を使用して Rust のコードを作成、編集、実行する方法を知っていること。
Rust の一般的な概念を理解する - Learn
https://docs.microsoft.com/ja-jp/learn/modules/rust-understand-common-concepts/
Rust の一般的な概念を理解する - Learn
Rust プログラム構造の概要 - Learn
次のコードを調べて、単純な Rust プログラムがどのように構造化されているかを確認しましょう。 fn main() { println!("Hello, world!"); } 最初の Rust プログラムでは、 main という名前の " 関数" が定義されています。 関数は、特定のタスクを実行するコードのブロックです。 プログラム内のコードをタスクに基づいてブロックに分割します。 この分割により、コードの理解と保守が容易になります。 タスクの関数を定義したら、そのタスクを実行する必要があるときに関数を呼び出すことができます。 すべての Rust プログラムには、 main という名前の関数が 1 つ 必要です。 main 関数内のコードは、常に、Rust プログラムで最初に実行されるコードです。 main 関数内または他の関数内から他の関数を呼び出すことができます。 Rust 内で関数を宣言するには、 fn キーワードを使用します。 関数名の後に、関数が入力として受け取るパラメーターまたは " 引数" の数をコンパイラに指示します。 引数のセットがかっこ () 内に一覧表示されます。 かっこが空の場合、関数には入力引数がありません。 main 関数は、入力引数を持たない関数の例です。 fn main()
Rust プログラム構造の概要 - Learn
https://docs.microsoft.com/ja-jp/learn/modules/rust-understand-common-concepts/1-program-structure
Rust プログラム構造の概要 - Learn
  • 関数について。関数は fn で記述。Ruby の def と同じ感じ。行は ; で終わるが、終わらない時は次の行を 4 インデントする。このあたりはフォーマッタがなんとかしてくれると信じる
  • println! はマクロ。{} は C 言語の %s みたいな感じ。数字などが渡されても文字列変換メソッドが入るので、型を区別しなくていいということ。
  • {} を書きたい時にはどうするんだろう。と思って色々やってみたが、これでいいのかな。\{\}ではなかった。
変数を作成して使用します - Learn
開発者は、データを操作するコンピューター プログラムを記述します。 データの収集、分析、保存、処理、共有、報告が行われます。 " 変数" を使用して、コード内で後で参照できる名前付き参照にデータを格納します。 Rust では、変数はキーワード let を使用して宣言されます。 各変数には一意の名前が付いています。 変数が宣言されている場合は、値にバインドできます。また、後でプログラム内で値をバインドすることもできます。 次のコードでは、 a_number という名前の変数を宣言しています。 let a_number; a_number 変数はまだ値にバインドされていません。 このステートメントを変更して、値を変数にバインドできます。 let a_number = 10; 注意 キーワード: 他のプログラミング言語と同様に、 fn や let などの特定の " キーワード" は、Rust でのみ使用するために予約されています。 キーワードを関数または変数の名前として使用することはできません。 別の例を見てみましょう。 次のコードでは、2 つの変数が宣言されています。 最初の変数が宣言され、数値にバインドされます。 2 番目の変数は宣言されていますが、値にバインドされていません。 プログラムの後の部分で、2 番目の変数の値が単語にバインドされています。 コードでは、変数の値を表示する println!
変数を作成して使用します - Learn
https://docs.microsoft.com/ja-jp/learn/modules/rust-understand-common-concepts/2-variables
変数を作成して使用します - Learn
  • 変数について。変数は let で設定。変数は不変(immutable)なので再代入は不可。
  • 可変(mutable)にしたければ mut を付ける。デフォルトではないということは滅多には使わない感じか。後で出てくる構造体の一部だけ変更するような時に使うくらいではないかとのこと。
  • 変数のシャドウ処理。mut だといつでも変更可能になってしまうので、シャドウ処理で同じ変数名を付けることができる。これだとあまり意味がないが、スコープが変わると意味があるかも。
データ型について学ぶ - Learn
Rust は静的型指定の言語です。 コンパイラは、プログラムをコンパイルして実行するために、コード内のすべての変数の正確なデータ型を認識している必要があります。 通常、コンパイラでは、バインドされた値に基づいて変数のデータ型を推測できます。 常にコード内で型を明示的に指定する必要はありません。 多くの型が可能な場合は、 型の注釈 を使用して、コンパイラに特定の型を通知する必要があります。 次の例では、 number 変数を 32 ビット整数として作成するようにコンパイラに指示しています。 変数名の後にデータ型 u32 を指定します。 変数名の後にコロン : が使用されていることに注意してください。 let number: u32 = 14; println!("The number is {}.", number); 変数の値を二重引用符で囲むと、コンパイラによって値が数値ではなくテキストとして解釈されます。 値の推定データ型が変数に指定された u32 データ型と一致しないため、コンパイラによってエラーが発行されます。 let number: u32 = "14"; コンパイラ エラー: Compiling playground v0.0.1 (/playground) error[E0308]: mismatched types --> src/main.rs:2:23 |
データ型について学ぶ - Learn
https://docs.microsoft.com/ja-jp/learn/modules/rust-understand-common-concepts/3-data-types
データ型について学ぶ - Learn
  • 型推論は自動で行われるが、自分で型を指定することもできる。 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/else 条件式を使用する - Learn
プログラミングの重要な部分は、データに基づいて意思決定を行うことです。 このユニットでは、条件をテストしてプログラムのアクションを制御する方法について説明します。 if および else キーワードを使用して、コード内に " 条件分岐" を作成できます。 多くのプログラミング言語によってこの機能が提供されており、同様の構文が使用されます。 if および else キーワードは、値をテストし、テスト結果に基づいてアクションを実行するために式と共に使用されます。 すべての条件式の結果は、ブール値の true または false になります。 2 つの数値が等しいかどうかをテストし、テスト結果に基づいてメッセージを出力する例を次に示します。 if 1 == 2 { println!("True, the numbers are equal."); // } else { println!("False, the numbers are not equal."); } 前の例では、 if の条件は式 1 == 2 で、これは false の値を持つブール型に評価されます。 他のほとんどの言語とは異なり、Rust の if ブロックは式としても機能できます。 条件分岐内のすべての実行ブロックでは、コードをコンパイルするために同じ型を返す必要があります。 let formal = true; let greeting = if formal { // if used here as an expression "Good day to you."
If/else 条件式を使用する - Learn
https://docs.microsoft.com/ja-jp/learn/modules/rust-understand-common-concepts/3a-if-else-expressions
If/else 条件式を使用する - Learn
  • if は条件式を記述。Ruby のように式には () はいらない
  • Ruby と同じく if 自体が値を返すので、C の三項演算子のように使える。let の文になるので最後にセミコロンが必要。Ruby だと「;」がいらないので気にならないが、Rust だと「};」の形になることに注意。
  • 複数の条件分岐は else if となる。
構造体と列挙型について学ぶ - Learn
構造体は、他の型で構成される型です。 構造体の要素は " フィールド" と呼ばれます。 タプルと同様に、構造体のフィールドは異なるデータ型を持つことができます。 構造体型の大きな利点は、各フィールドに名前を指定して値の意味を明確にできることです。 Rust プログラムで構造体を操作するには、まず構造体を名前で定義し、各フィールドのデータ型を指定します。 次に、別の名前を使用して構造体の " インスタンス" を作成します。 インスタンスを宣言する場合は、フィールドに特定の値を指定します。 Rust では、従来の構造体、タプル構造体、ユニット構造体という 3 つの構造体型がサポートされています。 これらの構造体型により、データのグループ化や操作を行うさまざまな方法がサポートされます。 は最もよく使われています。 構造体内の各フィールドには、名前とデータ型があります。 従来の構造体を定義した後は、構文 . を使用して構造体内のフィールドにアクセスできます。 タプル構造体 は従来の構造体に似ていますが、フィールドには名前がありません。 タプル構造体内のフィールドにアクセスするには、タプルのインデックス付けの場合と同じ構文 ( .
構造体と列挙型について学ぶ - Learn
https://docs.microsoft.com/ja-jp/learn/modules/rust-understand-common-concepts/4-structs-enums
構造体と列挙型について学ぶ - Learn
  • 構造体の種類は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 で関数を操作する - Learn
関数は、Rust 内でコードを実行する主要な方法です。 この言語で、最も重要な関数の 1 つは既に見た main 関数です。 このユニットでは、関数を定義して使用する方法を詳細に説明します。 前に説明したいくつかの関数の基本を確認しましょう。 Rust での関数定義は、 fn キーワードで始まります。 関数名の後に、関数の入力引数を、かっこ内のデータ型のコンマ区切りリストとして指定します。 中かっこは、関数本体の開始と終了の位置をコンパイラに伝えます。 fn main() { println!("Hello, world!"); goodbye(); } fn goodbye() { println!("Goodbye!"); } 関数を呼び出すには、その名前をかっこ内の入力引数と共に使用します。 関数に入力引数が存在しない場合は、かっこを空のままにします。 この例では、 main と goodbye の両方の関数に入力引数がありません。 main 関数の後に goodbye 関数が定義されていることにお気付きかと思います。 goodbye 関数は、 main を定義する前に定義しました。 Rust では、関数がファイル内のどこかに定義されている限り、ファイル内のどこに定義されているかは留意されません。 関数に入力引数がある場合は、各引数に名前を付け、関数宣言の最初にデータ型を指定します。 引数には変数のように名前が付けられているので、関数本体内で引数にアクセスできます。 ある数値が別の数値で割り切れるか (剰余がないか) どうかをチェックするための関数を宣言してみましょう。 fn is_divisible_by(dividend: u32, divisor: u32) { // If the divisor is zero, stop execution if divisor == 0 { println!("\nError!
Rust で関数を操作する - Learn
https://docs.microsoft.com/ja-jp/learn/modules/rust-understand-common-concepts/4a-functions
Rust で関数を操作する - Learn
  • 関数の基本
    • Rust の関数は fn で始まる。Ruby の def と同じイメージで。ただし、関数のスコープは {}。引数なしでも () は必要の様子。
  • 関数の入力引数
    • 引数は変数名の後ろに型を書く。Swift と同じ形だが、Swift や Objective-C のようにラベルはつけない。Swift の _ 付きのような感じ。今は IDE やエディタのサポートがあるので、ラベルがなくてもミスらないということか。
  • 関数の戻り値
    • 関数の戻り値は Swift と同じ形で関数名の後ろに -> で型を記述する。
    • 値を途中で返すときには、return 文を使うことができる。これはステートメントなので「;」が必要
    • Ruby と同じで最後に評価した式も返り値にになる。これはステートメントでないので、「;」をつけてはいけない。
    • デフォルトは最後に式を書く形だと思われる。
演習: 関数、構造体、および列挙型 - Learn
この演習では、列挙型、構造体、および関数を使用して、新車の注文を処理します。 課題は、コンパイルして実行できるようにサンプル コードを修正することです。 この演習用のサンプル コードを操作するには、次の 2 つの方法があります。 コードをコピーし、ローカルの開発環境で編集します。 準備済みの Rust Playground 内でコードを開きます。 サンプル コードで、単語 TO DO を探して、更新するセクションを特定します。 最初のタスクでは、列挙型の定義で構文の問題を修正して、コードをコンパイルします。 サンプル コードの最初のブロックを開きます。 次のコードをコピーし、ローカルの開発環境で編集します。 または、この準備済みの Rust Playground 内でコードを開きます。 // Declare Car struct to describe vehicle with four named fields struct Car { color: String, transmission: Transmission, convertible: bool, mileage: u32, } #[derive(PartialEq, Debug)]
演習: 関数、構造体、および列挙型 - Learn
https://docs.microsoft.com/ja-jp/learn/modules/rust-understand-common-concepts/4b-exercise-functions
演習: 関数、構造体、および列挙型 - Learn
  • 演習の解説は省略
    • 演習結果はこんな感じになりました。PartialEq だけがまだ説明がないですね。
コレクション型を使用する - Learn
タプルに加えて、Rust には、複数の値を 1 つの型にグループ化できる 複合型 が他にも多くあります。 配列は、メモリに連続して格納された同じ型のオブジェクトのコレクションです。 配列の長さまたは " サイズ" は、配列内の要素の数と同じです。 配列のサイズは、コード内で指定することも、コンパイラによって計算することもできます。 配列は、2 つの方法で定義できます。 長さが指定されていない、値のコンマ区切りリスト。 初期値、その後にセミコロン、次に配列の長さ。 どちらの場合も、コンテンツは角かっこ [] で囲まれます。 // Declare array, initialize all values, compiler infers length = 7 let days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; // Declare array, first value = "0", length = 5
コレクション型を使用する - Learn
https://docs.microsoft.com/ja-jp/learn/modules/rust-understand-common-concepts/7-collection-types
コレクション型を使用する - Learn
  • 配列
    • 配列の定義は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 になる
ループを使用したデータの反復処理 - Learn
多くの場合、プログラムには、その場で繰り返す必要があるコードのブロックがあります。 ループ式を使用して、繰り返しの実行方法をプログラムに指示できます。 電話帳のすべてのエントリを出力するには、ループ式を使用して、最初のエントリから最後のエントリまでを出力する方法をプログラムに指示できます。 Rust には、プログラムがコードのブロックを繰り返すようにする 3 つのループ式が用意されています。 loop: 手動で停止されない限り、繰り返します。 while: 条件が true の間は繰り返します。 for: コレクション内のすべての値に対して繰り返します。 このユニットでは、これらの各ループ式について見ていきます。 loop 式では、無限ループが作成されます。 このキーワードを使用すると、式本体のアクションを継続的に繰り返すことができます。 アクションは、ループを停止する直接アクションを実行するまで繰り返されます。 次の例では、"We loop forever!" というテキストが出力されます。 独力では停止しません。 println! アクションが繰り返され続けます。 loop { println!("We loop forever!"); } loop 式を使用する場合、ループを停止する唯一の方法は、プログラマが直接介入することです。 特定のコードを追加してループを停止させることができます。または、Ctrl+C などのキーボード命令を入力して、プログラムの実行を停止することもできます。 loop 式を停止する最も一般的な方法は、 break キーワードを使用してブレーク ポイントを設定することです。 loop { // Keep printing, printing, printing...
ループを使用したデータの反復処理 - Learn
https://docs.microsoft.com/ja-jp/learn/modules/rust-understand-common-concepts/7a-loops
ループを使用したデータの反復処理 - Learn
  • Rust のループは3つ
    • loop: 無限ループ
    • whlie: 条件が true の間ループ
    • for: コレクションを順にループ
  • loop
    • break まで止まらない
    • loop 自体も値を返せる
    • break の後に返す値を示せる
    • break が複数ある場合には、全てが同じ型でないとエラーになる
    • 値が明示的に返されなかった場合には、空のタプルが返却される
  • while
    • 条件を満足する間ループする

次のページはこちら
Rust 学習記録(2)
"[rust]": { "editor.formatOnSave": true, },
fn main() { println!("Hello, world!"); }
rustc main.rs ./main
cargo new hello-cargo
cargo run
fn main() { // The function declaration is not indented // First step in function body // Substep: execute before First step can be complete // Second step in function body // Substep A: execute before Second step can be complete // Substep B: execute before Second step can be complete // Sub-substep 1: execute before Substep B can be complete // Third step in function body, and so on... }
println!("The first letter of the English alphabet is {} and the last letter is {}.", 'A', 'Z');
fn main() { println!("{}{{}}", 1); }
let a_number; let a_word = "Ten"; a_number = 10; a_number = 15; // エラー
let mut a_number = 10; a_number = 15;
let shadow_num = 5; let shadow_num = shadow_num + 5;
let number: u32 = 14;
let number: u32 = "14"; // コンパイルエラー
let number_64 = 4.0; let number_32: f32 = 5.0;
let is_bigger = 1 > 4;
let tuple_e = ('e', 5i32, true);
if 1 == 2 { println!("True, the numbers are equal."); // } else { println!("False, the numbers are not equal."); }
let formal = true; let greeting = if formal { // if used here as an expression "Good day to you." // return a String } else { "Hey!" // return a String };
let num = 500 // num variable can be set at some point in the program let out_of_range: bool; if num < 0 { out_of_range = true; } else if num == 0 { out_of_range = true; } else if num > 512 { out_of_range = true; } else { out_of_range = false; }
// Classic struct with named fields struct Student { name: String, level: u8, pass: bool }
let user_1 = Student { name: String::from("Constance Sharma"), remote: true, level: 2 }; let user_2 = Student { name: String::from("Dyson Tan"), level: 5, remote: false };
println!("{}, level {}. Remote: {}. Grades: {}", user_1.name, user_1.level, user_1.remote); println!("{}, level {}. Remote: {}. Grades: {}", user_2.name, user_2.level, user_2.remote);
// Tuple struct with data types only struct Grades(char, char, char, char, f32);
// Instantiate tuple structs, pass values in same order as types defined let mark_1 = Grades('A', 'A', 'B', 'A', 3.75); let mark_2 = Grades('B', 'A', 'A', 'C', 3.25);
println!("{}, {}, {}. Average: {}", mark_1.0, mark_1.1, mark_1.2, mark_1.3, mark_1.4); println!("{}, {}, {}. Average: {}", mark_2.0, mark_2.1, mark_2.2, mark_2.3, mark_2.4);
enum WebEvent { // An enum variant can be like a unit struct without fields or data types WELoad, // An enum variant can be like a tuple struct with data types but no named fields WEKeys(String, char), // An enum variant can be like a classic struct with named fields and their data types WEClick { x: i64, y: i64 } }
// Define a tuple struct struct KeyPress(String, char); // Define a classic struct struct MouseClick { x: i64, y: i64 } // Redefine the enum variants to use the data from the new structs // Update the page Load variant to have the boolean type enum WebEvent { WELoad(bool), WEClick(MouseClick), WEKeys(KeyPress) }
let we_load = WebEvent::WELoad(true);
// Instantiate a MouseClick struct and bind the coordinate values let click = MouseClick { x: 100, y: 250 }; // Set the WEClick variant to use the data in the click struct let we_click = WebEvent::WEClick(click);
// Instantiate a KeyPress tuple and bind the key values let keys = KeyPress(String::from("Ctrl+"), 'N'); // Set the WEKeys variant to use the data in the keys tuple let we_key = WebEvent::WEKeys(keys);
println!("\nWebEvent enum structure: \n\n {:#?} \n\n {:#?} \n\n {:#?}", we_load, we_click, we_key);
// Define a tuple struct #[derive(Debug)] struct KeyPress(String, char); // Define a classic struct #[derive(Debug)] struct MouseClick { x: i64, y: i64, } // Redefine the enum variants to use the data from the new structs // Update the page Load variant to have the boolean type #[derive(Debug)] enum WebEvent { WELoad(bool), WEClick(MouseClick), WEKeys(KeyPress), }
fn main() { println!("Hello, world!"); goodbye(); } fn goodbye() { println!("Goodbye!"); }
fn is_divisible_by(dividend: u32, divisor: u32) { // If the divisor is zero, stop execution if divisor == 0 { println!("\nError! Division by zero is not allowed."); } else if dividend % divisor > 0 { println!("\n{} % {} has a remainder of {}.", dividend, divisor, (dividend % divisor)); } else { println!("\n{} % {} has no remainder.", dividend, divisor); } } fn main() { is_divisible_by(12, 4); is_divisible_by(13, 5); is_divisible_by(14, 0); }
fn is_zero(input: u8) -> bool { if input == 0 { return true; } false } fn main() { if is_zero(0) { println!("The value is zero."); } }
// Declare Car struct to describe vehicle with four named fields struct Car { color: String, transmission: Transmission, convertible: bool, mileage: u32, } #[derive(PartialEq, Debug)] // Declare enum for Car transmission type // TO DO: Fix enum definition so code compiles enum Transmission { Manual, SemiAuto, Automatic, } // Build a "Car" by using values from the input arguments // - Color of car (String) // - Transmission type (enum value) // - Convertible (boolean, true if car is a convertible) fn car_factory(color: String, transmission: Transmission, convertible: bool) -> Car { // TO DO: Complete "car" declaration to be an instance of a "Car" struct // Use the values of the input arguments // All new cars always have zero mileage Car { color: color, transmission: transmission, convertible: convertible, mileage: 0, } } fn main() { // We have orders for three new cars! // We'll declare a mutable car variable and reuse it for all the cars let mut car = car_factory(String::from("Red"), Transmission::Manual, false); println!( "Car 1 = {}, {:?} transmission, convertible: {}, mileage: {}", car.color, car.transmission, car.convertible, car.mileage ); car = car_factory(String::from("Silver"), Transmission::Automatic, true); println!( "Car 2 = {}, {:?} transmission, convertible: {}, mileage: {}", car.color, car.transmission, car.convertible, car.mileage ); car = car_factory(String::from("Yellow"), Transmission::SemiAuto, false); println!( "Car 3 = {}, {:?} transmission, convertible: {}, mileage: {}", car.color, car.transmission, car.convertible, car.mileage ); }
// Declare array, initialize all values, compiler infers length = 7 let days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; // Declare array, first value = "0", length = 5 let bytes = [0; 5];
// Set first day of week let first = days[0]; // Set second day of week let second = days[1]; // Set seventh day of week, use wrong index - should be 6 let seventh = days[7]; // コンパイルエラー
// Declare vector, initialize with three values let three_nums = vec![15, 3, 46]; println!("Initial vector: {:?}", three_nums); // Declare vector, first value = "0", length = 5 let zeroes = vec![0; 5]; println!("Zeroes: {:?}", zeroes);
// Create empty vector, declare vector mutable so it can grow and shrink let mut fruit = Vec::new();
// Push values onto end of vector, type changes from generic `T` to String fruit.push("Apple"); fruit.push("Banana"); fruit.push("Cherry"); println!("Fruits: {:?}", fruit); fruit.push(1); // コンパイルエラー
// Pop off value at end of vector // Call pop() method from inside println! macro println!("Pop off: {:?}", fruit.pop()); println!("Fruits: {:?}", fruit);
// Declare vector, initialize with three values let mut index_vec = vec![15, 3, 46]; let three = index_vec[1]; println!("Vector: {:?}, three = {}", index_vec, three);
// Access vector with out-of-bounds index let beyond = index_vec[10]; println!("{}", beyond); パニックメッセージ thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 10', src/main.rs:7:18
use std::collections::HashMap; let mut reviews: HashMap<String, String> = HashMap::new(); reviews.insert("Ancient Roman History".to_string(), "Very accurate.".to_string()); reviews.insert("Cooking with Rhubarb".to_string(), "Sweet recipes.".to_string()); reviews.insert("Programming in Rust".to_string(), "Great examples.".to_string());
// Look for a specific review let book: &str = "Programming in Rust"; println!("\nReview for \'{}\': {:?}", book, reviews.get(book)); 結果 Review for 'Programming in Rust': Some("Great examples.")
// Remove book review let obsolete: &str = "Ancient Roman History"; println!("\n'{}\' removed.", obsolete); reviews.remove(obsolete); // Confirm book review removed println!("\nReview for \'{}\': {:?}", obsolete, reviews.get(obsolete)); 結果 'Ancient Roman History' removed. Review for 'Ancient Roman History': None
let mut counter = 1; // stop_loop is set when loop stops let stop_loop = loop { counter *= 2; if counter > 100 { // Stop loop, return counter value break counter; } }; // Loop should break when counter = 128 println!("Break the loop at counter = {}.", stop_loop);
let mut counter = 0; while counter < 5 { println!("We loop a while..."); counter = counter + 1; }