Rust言語用語集:技術解説

【本文書の使い方】

本用語集は、Rustプログラミング言語に関する基本用語と重要な特徴機能を解説する技術文書である。Rust固有の概念に加え、プログラミング基本概念の説明も含めている。各用語には詳細な説明とコード例が付属しており、用語間のリンクをたどることで関連概念を効率的に学習できる。プログラミング初学者から中級者を対象とする。

推奨される学習順序:

  1. 基本的なデータ型と変数の概念を理解する(変数初期化
  2. 所有権システムの基本概念と規則を理解する
  3. 借用とライフタイムの仕組みを学ぶ
  4. 制御文の仕組みを学ぶ(制御文ifforwhilematch
  5. 関数の定義と呼び出しを習得する(関数パラメータ引数
  6. エラーハンドリングの方法を習得する
  7. イテレータクロージャを活用する
  8. 構造体とトレイトの概念を学ぶ(構造体トレイト実装
  9. 並行性の概念を理解する

辞書的利用:用語集から必要な用語を直接参照することも可能である。

【目次】

  1. 主要概念の解説
  2. 用語
  3. Rustの記号・キーワード等
  4. 索引

主要概念の解説

本セクションでは、Rustプログラミング言語の重要な特徴機能を解説する。これらの概念は相互に関連しており、Rustのメモリ安全性と高性能を実現する基盤となっている。

所有権システム(Ownership System)

Rustの所有権システムは、メモリ安全性を保証する中核的な機能である。各値には唯一の所有者が存在し、所有者がスコープを抜けると値は自動的に解放される。この仕組みにより、ガベージコレクタなしでメモリリークやダングリングポインタを防ぐことができる。

所有権の基本ルール

fn main() {
    let s1 = String::from("hello");
    let s2 = s1; // s1の所有権がs2に移動(ムーブ)
    // println!("{}", s1); // エラー:s1はもう使用できない
    println!("{}", s2);    // OK
}

関連項目:所有権ムーブ借用

借用とライフタイム(Borrowing and Lifetimes)

借用は、所有権を移動せずに値への参照を渡す仕組みである。借用には不変借用(&)と可変借用(&mut)の2種類がある。ライフタイムは、参照が有効な期間を示す概念であり、コンパイラが参照の安全性を保証するために使用する。

借用の規則

fn main() {
    let mut s = String::from("hello");
    change(&mut s);
    println!("{}", s);
}

fn change(s: &mut String) {
    s.push_str(", world");
}

関連項目:借用ライフタイム参照

クロージャ(Closures)

クロージャは、環境の変数をキャプチャできる匿名関数である。クロージャはfnキーワードを使わず、|引数| 式の構文で定義する。クロージャは、moveキーワードを使用することで、キャプチャした変数の所有権を取得することもできる。

fn main() {
    let add_one = |x| x + 1;
    println!("{}", add_one(5)); // 6

    let v = vec![1, 2, 3];
    let doubled: Vec<_> = v.iter().map(|x| x * 2).collect();
}

関連項目:moveイテレータ

エラーハンドリング(Error Handling)

Rustは、回復可能なエラーに対してResult型を、回復不可能なエラーに対してpanic!マクロを使用する。Result型は、OkErrのバリアントを持つ列挙型である。?演算子を使用することで、エラーを簡潔に伝播できる。

use std::fs::File;

fn read_file() -> Result<String, std::io::Error> {
    let mut contents = String::new();
    File::open("hello.txt")?.read_to_string(&mut contents)?;
    Ok(contents)
}

fn main() {
    let f = File::open("hello.txt");
    let f = match f {
        Ok(file) => file,
        Err(error) => {
            panic!("ファイルを開けません: {:?}", error);
        }
    };
}

関連項目:エラーResult型Option型?演算子

イテレータ(Iterators)

イテレータは、一連の要素を順番に処理するための抽象化である。Rustのイテレータは遅延評価され、ゼロコスト抽象化の原則に基づいて実装されている。mapfiltersumなどのメソッドを連鎖させることで、効率的なデータ処理が可能となる。

fn main() {
    let v = vec![1, 2, 3];
    let sum: i32 = v.iter().map(|x| x * 2).sum();
    println!("{}", sum); // 12

    let even: Vec<_> = v.iter().filter(|&x| x % 2 == 0).collect();
}

関連項目:forクロージャ

並行性(Concurrency)

Rustの並行性モデルは、所有権システムと型システムを活用することで、データ競合をコンパイル時に防ぐ。spawn関数を使用してスレッドを生成し、チャネルやMutexなどの同期プリミティブを使用してスレッド間通信を行う。

use std::thread;
use std::sync::mpsc;

fn main() {
    let handle = thread::spawn(|| {
        println!("別スレッドから");
    });
    handle.join().unwrap();

    // チャネルを使用したスレッド間通信
    let (tx, rx) = mpsc::channel();
    thread::spawn(move || {
        tx.send("メッセージ").unwrap();
    });
    let received = rx.recv().unwrap();
}

関連項目:moveスマートポインタ


用語

本セクションでは、プログラミングに関する基本用語を五十音順に解説する。各用語について、Rustでの扱いを中心に説明し、必要に応じて他の言語との比較も示す。

アクセス

データの読み出しや書き込みを行うことをアクセスという。「メモリをアクセスする」、「ディスクをアクセスする」などのように使用する。Rustでは、借用規則により、安全なアクセスが保証される。

イミュータブル

変更不可能な状態をイミュータブルという。Rustでは、変数デフォルトでイミュータブルであり、明示的にmutキーワードを付けることでミュータブル(変更可能)になる。この仕組みにより、意図しない変更を防ぎ、コードの安全性を高めることができる。

let x = 5;      // イミュータブル
// x = 6;       // エラー:イミュータブルな変数に再代入できない
let mut y = 10; // ミュータブル
y = 11;         // OK

関連項目:ミュータブル変数

入れ子

ある構造の内部に同じ種類の構造が含まれている状態を入れ子という。ループや条件分岐、関数呼び出しなどで入れ子構造が使用される。

for i in 0..10 {
    for j in 0..20 {
        println!("i={}, j={}", i, j);
    }
}

// 2次元ベクタの作成
let x: Vec<Vec<i32>> = vec![vec![0; 20]; 10];

エディタ

エディタとは、テキストやプログラムを編集する機能を持ったソフトウェアである。Rustプログラミング用のエディタには、Visual Studio Code(rust-analyzerプラグイン)、IntelliJ IDEA(Rustプラグイン)、Vimなどがある。

エラー

プログラムの実行中または実行前に発生する問題をエラーという。Rustでは、エラーを以下のように分類する。

関連項目:エラーハンドリングResult型

演算子

演算子とは、1個または複数のオペランドに対して演算を行うための記号である。Rustの代表的な演算子を以下に示す。

算術演算子
    +     加算
    -     減算
    *     乗算
    /     除算
    %     剰余

比較演算子
    ==    等しい
    !=    等しくない
    <     より小さい
    <=    以下
    >     より大きい
    >=    以上

論理演算子
    &&    論理積
    ||    論理和
    !     否定

ビット演算子
    &     ビット積
    |     ビット和
    ^     ビット排他的論理和
    <<    左シフト
    >>    右シフト

代入演算子
    =     代入
    +=    加算代入
    -=    減算代入
    *=    乗算代入
    /=    除算代入

その他
    []    インデックスアクセス
    .     フィールドアクセス、メソッド呼び出し
    &     参照
    *     参照外し
    ::    パス区切り
    ?     エラー伝播

オーバーフロー

演算結果の絶対値が、データ型で表現可能な範囲を超えた状態をオーバーフローという。Rustでは、デバッグビルドでオーバーフローが発生するとpanicするが、リリースビルドでは循環的に値が折り返される(2の補数による)。明示的な動作を制御するには、以下のメソッドを使用する。

let x: u8 = 255;
let y = x.wrapping_add(1);      // 0(循環)
let z = x.checked_add(1);       // None(オーバーフローを検出)
let w = x.saturating_add(1);    // 255(最大値で飽和)

オペランド

演算子による演算の対象となる値や変数をオペランドという。例えば、「a + b」という式では、aとbがオペランドであり、+が演算子である。

改行

テキストの表示位置を次の行の先頭に移動させる動作を改行という。Rustでは、文字列中に\nを記述することで改行を表現する。

println!("1行目\n2行目\n3行目");

関連項目:改行文字

改行文字

改行を表す特殊文字を改行文字という。Rustでは\nで表現する。改行の内部表現はオペレーティングシステムによって異なるが、Rustの標準ライブラリは適切に処理する。

型とは、データの種類と、そのデータに対して実行可能な操作を定義するものである。Rustは静的型付け言語であり、変数の型はコンパイル時に決定される。これにより、型に関するエラーを実行前に検出できる。Rustの主な組み込み型を以下に示す。

仮引数

仮引数(パラメータ)とは、関数定義において宣言される変数である。関数が呼び出されると、実引数の値がパラメータに渡される。Rustでは、パラメータの型を必ず明示する必要がある。

fn greet(name: &str) {  // nameが仮引数
    println!("Hello, {}", name);
}

greet("Alice");  // "Alice"が実引数

関連項目:引数関数

関数

関数とは、特定の処理をまとめた再利用可能なコードブロックである。引数を受け取り、処理を実行し、結果を返すことができる。関数を使用することで、コードの重複を避け、可読性と保守性を向上させることができる。

【関数の定義】

Rustではfnキーワードを使用して関数を定義する。パラメータの型と戻り値の型を明示する必要がある。

fn add(a: i32, b: i32) -> i32 {
    a + b  // 最後の式が戻り値(セミコロンなし)
}

let result = add(3, 5);  // resultは8

【戻り値】

関数はreturn文で値を返すか、最後の式をセミコロンなしで記述することで値を返す。戻り値がない場合は、ユニット型()を返す。

fn greet(name: &str) {
    println!("Hello, {}", name);
    // ユニット型()が返される
}

fn multiply(a: i32, b: i32) -> i32 {
    return a * b;  // 明示的なreturn
}

fn square(x: i32) -> i32 {
    x * x  // 最後の式が戻り値
}

【関数呼び出しの流れ】

プログラムは通常、上から下へ順番に実行される。関数呼び出しがあると、制御は関数の内部に移り、関数の処理が完了すると呼び出し元に戻る。

関連項目:fn仮引数引数

擬似乱数

数学的なアルゴリズムによって生成される、乱数のように見える数列を擬似乱数という。Rustではrandクレートを使用して擬似乱数を生成する。

use rand::Rng;

let mut rng = rand::thread_rng();
let x: f64 = rng.gen();  // 0.0以上1.0未満
let y: u32 = rng.gen_range(1..=100);  // 1以上100以下

クレート

クレートは、Rustのコンパイル単位である。ライブラリクレートまたはバイナリクレートのいずれかである。クレートは、関連するモジュールの集合であり、Cargo.tomlファイルで依存関係を管理する。

関連項目:モジュールCargo

クローン

値の深いコピーを作成することをクローンという。Rustでは、Cloneトレイトを実装した型に対してclone()メソッドを呼び出すことで、値の完全なコピーを作成できる。クローンは、所有権を維持したまま、元の値のコピーを別の変数で使用する必要がある場合に有用である。

let s1 = String::from("hello");
let s2 = s1.clone();  // s1の深いコピー
println!("{}, {}", s1, s2);  // 両方とも使用可能

関連項目:Copy所有権

繰り返し

同じ処理を条件に基づいて複数回実行することを繰り返し(ループ)という。Rustでは、for文、while文、loop文が繰り返し処理に使用される。

関連項目:ループforwhileloop

コーディング

ソースプログラムを作成する作業をコーディングという。プログラミングが設計から実装までの全工程を指すのに対し、コーディングは設計に基づいてコードを記述する工程を指すことが多い。

構造体

複数のデータを1つにまとめたデータ型を構造体という。Rustではstructキーワードを使用して構造体を定義する。構造体を使用することで、関連するデータをグループ化し、コードの意味を明確にすることができる。

struct Person {
    name: String,
    age: u32,
    height: f64,
}

let person = Person {
    name: String::from("Alice"),
    age: 30,
    height: 165.5,
};

println!("名前: {}", person.name);

構造体には、名前付きフィールドを持つ構造体、タプル構造体、ユニット構造体の3種類がある。

関連項目:実装struct

コメント

プログラム中に記述する注釈をコメントという。コメントはプログラムの実行時に無視され、コードの説明や使用上の注意を記述するために使用される。

Rustでは、//記号から行末までが1行コメント、/**/で囲んだ部分が複数行コメントとなる。

// これは1行コメント
let x = 10;  // 行末コメント

/*
   これは複数行コメント
   複数行にわたって記述できる
*/

/// これはドキュメンテーションコメント
/// 関数やモジュールの説明に使用する
fn example() {
    // 処理
}

コンパイル

プログラムのソースコードを、コンピュータが実行可能な形式に変換する処理をコンパイルという。Rustでは、ソースコードは機械語に直接コンパイルされ、実行可能ファイルが生成される。Rustコンパイラ(rustc)は、LLVMを使用して最適化されたネイティブコードを生成する。

再帰的呼び出し

関数が自分自身を呼び出すことを再帰的呼び出し(再帰)という。再帰は、問題を同じ構造の小さな問題に分割して解く場合に有効である。

以下は、ハノイの塔問題を再帰で解くRustプログラムである。

fn hanoi(n: u32, source: &str, auxiliary: &str, target: &str) {
    if n == 1 {
        println!("円盤1を{}から{}へ移動", source, target);
        return;
    }
    hanoi(n - 1, source, target, auxiliary);
    println!("円盤{}を{}から{}へ移動", n, source, target);
    hanoi(n - 1, auxiliary, source, target);
}

hanoi(3, "A", "B", "C");

三角関数

角度に関する数学関数を三角関数という。Rustでは標準ライブラリのf32およびf64型のメソッドとして三角関数が提供される。引数と戻り値の角度の単位はラジアンである。

use std::f64::consts::PI;

let x = 0.5_f64;
let sine = x.sin();     // サイン
let cosine = x.cos();   // コサイン
let tangent = x.tan();  // タンジェント
let arcsine = sine.asin();   // 逆サイン
let arccosine = cosine.acos(); // 逆コサイン
let arctangent = tangent.atan(); // 逆タンジェント

算術

数値に対する基本的な計算(加減乗除など)を算術という。

借用

借用は、所有権を移動させることなく、値への参照を作成することである。借用により、値を共有しつつメモリ安全性を保つことができる。借用には不変借用可変借用の2種類がある。

fn calculate_length(s: &String) -> usize {
    s.len()  // 値を変更せず読み取る
}

fn change(s: &mut String) {
    s.push_str(", world");  // 値を変更
}

let mut s = String::from("hello");
let len = calculate_length(&s);  // 不変借用
change(&mut s);                  // 可変借用

関連項目:借用とライフタイム所有権ライフタイム参照

参照

参照は、値への借用を表す型である。&演算子で作成し、*演算子で参照外しを行う。Rustの参照は常に有効なデータを指すことが保証される(ダングリングポインタは発生しない)。

let x = 5;
let r = &x;      // xへの参照
println!("{}", *r);  // 参照外し

let mut y = 10;
let mr = &mut y;  // 可変参照
*mr += 5;
println!("{}", y);  // 15

関連項目:借用ポインタ

演算子オペランドの組み合わせで構成され、評価すると値を生成するコードの断片を式という。Rustでは、ほとんどの構文が式であり、値を返す。この特性により、より柔軟で簡潔なコードを記述できる。

// Rustの式の例
30
x
x + y
a * b + c
vec.len()
x < 100

// ブロックも式
let y = {
    let x = 3;
    x + 1  // 4を返す
};

// if式も値を返す
let number = if condition { 5 } else { 6 };

関連項目:評価

識別子

変数、関数、構造体、トレイトなどに付ける名前を識別子という。Rustの識別子は以下の規則に従う。

字下げ

プログラムの行頭に空白やタブを挿入することを字下げ(インデント)という。Rustでは、インデントは構文上必須ではないが、4つの空白を使用することが標準的な慣例である(rustfmtで自動整形される)。

if x < 100 {
    println!("xは100未満");  // 4つの空白でインデント
    let y = x * 2;
}

実行形式ファイル

機械語で記述され、コンピュータが直接実行できる形式のファイルを実行形式ファイル(実行ファイル)という。Rustでは、コンパイルによって実行形式ファイルが生成される。Windowsでは.exe、Unix系ではELF形式が使用される。

ジャンプ文

プログラムの実行位置を移動させる文をジャンプ文という。Rustのジャンプ文には以下がある。

関連項目:制御文

初期化

変数やオブジェクトに最初の値を設定することを初期化という。Rustでは、変数は使用前に必ず初期化する必要がある(未初期化変数の使用はコンパイルエラー)。これにより、未初期化変数の使用による予期しない動作を防ぐことができる。

let x: i32 = 10;              // 整数
let rate: f64 = 124.10;       // 浮動小数点数
let name: &str = "Alice";     // 文字列スライス
let numbers: Vec<i32> = vec![1, 2, 3];  // ベクタ

// 型推論も使用可能
let y = 5;  // i32と推論される

書式文字列

データを文字列に変換する際の形式を指定する文字列を書式文字列という。Rustでは、format!マクロ、println!マクロなどで書式文字列を使用する。

let name = "Alice";
let age = 30;

// {}プレースホルダ
println!("{}は{}歳です", name, age);

// 名前付き引数
println!("{name}は{age}歳です", name=name, age=age);

// デバッグ出力({:?})
let vec = vec![1, 2, 3];
println!("{:?}", vec);

// 書式指定
let pi = 3.141592653589793;
println!("{:.2}", pi);  // 小数点以下2桁:3.14

Rustでは、ブール型のtrueのみが真として評価される。他の言語とは異なり、0以外の数値や空でない文字列は真として評価されない。

関連項目:true / false

数字

数字とは、0から9までの10個の記号である。

0 1 2 3 4 5 6 7 8 9

スライス

スライスは、コレクションの一部への参照である。所有権を持たず、元のデータへの窓として機能する。スライスを使用することで、データ全体をコピーせずに部分的にアクセスできる。

let s = String::from("hello world");
let hello = &s[0..5];   // "hello"へのスライス
let world = &s[6..11];  // "world"へのスライス

let a = [1, 2, 3, 4, 5];
let slice = &a[1..3];   // [2, 3]へのスライス

関連項目:配列ベクタ

制御文

プログラムの実行順序を変更する文を制御文という。制御文には以下の種類がある。

  1. 繰り返し文for文、while文、loop
  2. ジャンプ文breakcontinuereturn
  3. 条件分岐if式、match

宣言

変数や関数の名前と型を指定することを宣言という。Rustでは、変数の宣言にletキーワードを使用する。型は明示的に指定することも、型推論に任せることもできる。

let x: i32 = 10;  // 型を明示
let y = 20;       // 型推論(i32)
let name: String = String::from("Alice");

所有権

Rustの最も重要な概念の一つである所有権は、メモリ安全性を保証する仕組みである。所有権システムにより、ガベージコレクタなしでメモリ安全性とデータ競合の防止が実現される。所有権の規則は以下の通りである。

{
    let s = String::from("hello"); // sが所有者
    // sを使用できる
} // スコープ終了、sが破棄される

let s1 = String::from("hello");
let s2 = s1; // 所有権がs1からs2に移動(ムーブ)
// println!("{}", s1); // エラー:s1はもう使えない
println!("{}", s2);    // OK

関連項目:所有権システム借用ライフタイムムーブ

ソースファイル

プログラムのソースコードを保存したテキストファイルをソースファイルという。Rustのソースファイルの拡張子は.rsである。

ソースプログラム

人間が読み書きできる形式で記述されたプログラムをソースプログラム(ソースコード)という。Rustでは、ソースコードはコンパイラによって機械語に変換される。

データ構造

データを効率的に格納・操作するための形式をデータ構造という。Rustの標準ライブラリには、Vec(ベクタ)、HashMap(ハッシュマップ)、BTreeMap(二分探索木マップ)、HashSet(ハッシュ集合)、LinkedList(連結リスト)などのデータ構造が提供されている。

テキストファイル

人間が読める文字のみで構成されたファイルをテキストファイルという。バイナリファイルと対比される概念である。

テスト

プログラムが仕様通りに動作するかを検証し、バグを発見する作業をテストという。Rustでは、#[test]属性を使用してテスト関数を定義し、cargo testコマンドで実行する。

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_add() {
        assert_eq!(add(2, 3), 5);
    }

    #[test]
    #[should_panic]
    fn test_panic() {
        panic!("テスト用のパニック");
    }
}

デバッガ

プログラムのバグを発見・修正するための支援ツールをデバッガという。ブレークポイントの設定、ステップ実行、変数の監視などの機能を提供する。Rustでは、gdblldb、IDE内蔵のデバッガなどが使用される。

デバッグ

プログラムのバグを発見し、修正する作業をデバッグという。

トレイト

トレイトは、特定の型が持つべき機能を定義するRustの機能である。他の言語のインターフェースに相当する。トレイトはtraitキーワードで定義し、implキーワードで実装する。トレイトを使用することで、異なる型に共通の動作を定義し、ジェネリクスと組み合わせて柔軟なコードを記述できる。

trait Summary {
    fn summarize(&self) -> String;
}

struct Article {
    title: String,
    content: String,
}

impl Summary for Article {
    fn summarize(&self) -> String {
        format!("{}: {}", self.title, self.content)
    }
}

Rustの標準ライブラリには、Clone、Copy、Debug、Display、Dropなどの重要なトレイトが定義されている。

関連項目:実装trait

Rustでは、ブール型のfalseのみが偽と評価される。他の言語とは異なり、0や空文字列は偽として評価されない。

if false {
    println!("実行されない");
}

関連項目:true / false

分配束縛

タプルや構造体などの複合型から値を取り出して、複数の変数に同時に代入することを分配束縛(デストラクチャリング)という。分配束縛を使用することで、複合型のデータを簡潔に扱うことができる。

// タプルの分配
let (x, y, z) = (1, 2, 3);

// 構造体の分配
struct Point { x: i32, y: i32 }
let p = Point { x: 0, y: 7 };
let Point { x, y } = p;

// パターンマッチでの分配
match p {
    Point { x: 0, y } => println!("y軸上の点: y = {}", y),
    Point { x, y: 0 } => println!("x軸上の点: x = {}", x),
    Point { x, y } => println!("それ以外: ({}, {})", x, y),
}

ブロック

複数の文をまとめた単位をブロックという。Rustでは、波括弧{}でブロックの範囲を示す。ブロックは式であり、最後の式の値を返す。

fn example() {
    // ブロック開始
    let x = 5;
    let y = 10;
    println!("{}", x + y);
    // ブロック終了
}

// ブロックは式として使用できる
let result = {
    let x = 3;
    x + 1  // 4を返す
};

プログラム

コンピュータに実行させる命令の集まりをプログラムという。オペレーティングシステムなどのシステムプログラムと、特定の用途に使用するアプリケーションプログラムに分類される。

プログラミング

プログラムを設計・作成する作業をプログラミングという。

プログラミング言語

プログラムを記述するための人工言語をプログラミング言語という。Rust、Python、JavaScript、C、C++、Java、Go、Kotlinなどがある。

プログラミングスタイル

コードの書き方に関する規約やガイドラインをプログラミングスタイルという。Rustでは、rustfmtツールによる自動整形が標準であり、以下の慣例が使用されている。

プロセッサ

機械語のプログラムを解釈・実行するハードウェアをプロセッサ(CPU)という。

プログラムを構成する実行単位を文という。Rustでは、文は値を返さない。主な文の種類を以下に示す。

Rustでは、if、loop、matchなどは文ではなく式である。

関連項目:

変数

データを格納するための名前付きの領域を変数という。Rustでは、変数はletキーワードで宣言し、デフォルトでイミュータブルである。

// 不変変数
let x = 10;
// x = 11;  // エラー

// 可変変数
let mut y = 20;
y = 21;  // OK

// 型注釈
let z: i32 = 30;

// シャドーイング(同じ名前で新しい変数を作成)
let x = 5;
let x = x + 1;  // 新しいxを作成
let x = "文字列";  // 型も変更可能

関連項目:所有権イミュータブルlet

ベクタ

ベクタ(Vec<T>)は、動的にサイズが変更可能な配列である。ヒープに確保され、要素の追加や削除が可能である。要素数が不明または変化する場合に使用する。

// ベクタの作成
let mut vec = Vec::new();
vec.push(1);
vec.push(2);
vec.push(3);

// vecマクロを使用
let vec = vec![1, 2, 3, 4, 5];

// 要素へのアクセス
println!("{}", vec[0]);  // 1
println!("{:?}", vec.get(10));  // None(範囲外)

// イテレーション
for item in &vec {
    println!("{}", item);
}

関連項目:配列vec!

配列

同じ型の要素が固定サイズで並んだデータ構造を配列という。Rustの配列はスタックに確保され、サイズはコンパイル時に決定される。配列は固定サイズであるため、要素数が決まっている場合に使用する。

// 配列の作成
let numbers: [i32; 5] = [1, 2, 3, 4, 5];
let zeros = [0; 100];  // 100個の0

// 要素へのアクセス
println!("{}", numbers[0]);  // 1(インデックスは0から始まる)

// 範囲外アクセスはパニックを引き起こす
// let x = numbers[10];  // パニック

動的なサイズが必要な場合は、Vec型(ベクタ)を使用する。

関連項目:ベクタスライス

ハノイの塔

ハノイの塔は、再帰的呼び出しの典型的な例題である。3本の柱と複数の円盤があり、「大きな円盤の上に小さな円盤のみ置ける」という制約のもと、円盤を1枚ずつ移動させて、すべての円盤を別の柱に移す問題である。

引数

関数呼び出し時に渡す値を引数(実引数)という。関数定義側で受け取る変数は仮引数(パラメータ)と呼ばれる。

関連項目:仮引数関数

評価

式からその値を計算することを評価という。

関連項目:

標準出力

プログラムの出力先として既定で使用される出力チャネルを標準出力という。通常はディスプレイ(コンソール)に接続されている。Rustでは、println!マクロやprint!マクロが標準出力への出力を行う。

標準入力

プログラムの入力元として既定で使用される入力チャネルを標準入力という。通常はキーボードに接続されている。Rustでは、std::io::stdin()関数で標準入力にアクセスする。

use std::io;

let mut input = String::new();
io::stdin().read_line(&mut input).expect("入力の読み込みに失敗");

ファイル

ディスクなどの記憶装置に保存されるデータの単位をファイルという。ファイルの読み書きには、オープン(開く)、読み書き操作、クローズ(閉じる)という手順が必要である。

【Rustでのファイル操作】

use std::fs::File;
use std::io::{Read, Write};

// ファイルの読み込み
let mut file = File::open("input.txt")?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;

// ファイルへの書き込み
let mut file = File::create("output.txt")?;
file.write_all(b"Hello, World!")?;

// より便利な関数
use std::fs;
let contents = fs::read_to_string("input.txt")?;
fs::write("output.txt", "Hello, World!")?;

ポインタ

メモリ上のアドレスを格納する変数をポインタという。C言語の概念であり、Rustでは参照スマートポインタ(Box、Rc、Arcなど)を使用して、安全にメモリを操作する。

// 参照(安全なポインタ)
let x = 5;
let r = &x;

// Box(ヒープ割り当て)
let b = Box::new(5);

// Rc(参照カウント)
use std::rc::Rc;
let rc = Rc::new(5);
let rc2 = Rc::clone(&rc);

関連項目:参照スマートポインタ

マクロ

マクロは、コードを生成するコードである。Rustでは、マクロは!記号で識別され、コンパイル時に展開される。マクロを使用することで、繰り返しの多いコードを簡潔に記述できる。

// 組み込みマクロ
println!("Hello, {}", name);  // 書式付き出力
vec![1, 2, 3];                // ベクタ作成
panic!("エラー");             // パニック

// カスタムマクロの定義
macro_rules! say_hello {
    () => {
        println!("Hello!");
    };
}

say_hello!();

ムーブ

所有権がある変数から別の変数に移動することをムーブという。ムーブ後、元の変数は使用できなくなる。これにより、二重解放やデータ競合を防ぐことができる。

let s1 = String::from("hello");
let s2 = s1;  // s1からs2へ所有権がムーブ
// println!("{}", s1);  // エラー:s1はもう使えない
println!("{}", s2);     // OK

Copyトレイトを実装している型(整数、浮動小数点数、ブール値など)は、ムーブではなくコピーされる。

関連項目:所有権Copymove

ミュータブル

変更可能な状態をミュータブルという。Rustでは、mutキーワードを付けることで変数をミュータブルにする。

let mut x = 5;
x = 6;  // OK

let y = 10;
// y = 11;  // エラー:イミュータブルな変数

関連項目:イミュータブルmut

モジュール

モジュールは、コードを整理し、名前空間を提供する仕組みである。modキーワードでモジュールを定義する。モジュールを使用することで、コードを論理的に分割し、可読性と保守性を向上させることができる。

mod my_module {
    pub fn public_function() {
        println!("公開関数");
    }

    fn private_function() {
        println!("非公開関数");
    }
}

// モジュールの使用
my_module::public_function();

関連項目:クレートmod

文字型

1文字を格納するデータ型を文字型という。Rustではchar型が文字を表し、4バイトのUnicodeスカラ値である。

let c: char = 'z';
let emoji: char = '😀';
let japanese: char = 'あ';

文字列データ

文字の並びを表すデータを文字列という。Rustでは、&str型(文字列スライス)とString型(所有権を持つヒープ割り当て文字列)の2種類がある。

// 文字列スライス(不変)
let s1: &str = "Hello";

// String型(可変可能)
let mut s2: String = String::from("Hello");
s2.push_str(", world");

// 文字列操作
let length = s2.len();
let upper = s2.to_uppercase();
let combined = format!("{} {}", s1, s2);

メモリ

データやプログラムを一時的に記憶する装置をメモリという。各記憶位置にはアドレスが割り当てられている。Rustでは、メモリはスタックヒープに分類され、所有権システムによって安全に管理される。

列挙型

複数の異なる値のバリアントを定義できるデータ型を列挙型という。Rustではenumキーワードで定義する。各バリアントはデータを保持でき、match式でパターンマッチングを行う。列挙型を使用することで、型安全な状態管理やエラー処理が可能になる。

enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(i32, i32, i32),
}

let msg = Message::Write(String::from("Hello"));
match msg {
    Message::Quit => println!("終了"),
    Message::Write(text) => println!("{}", text),
    _ => println!("その他のメッセージ"),
}

関連項目:Option型Result型enum

ライフタイム

ライフタイムは、参照が有効である期間を示すRustの概念である。Rustコンパイラは、すべての借用が有効なデータを指していることを保証するために、ライフタイムを使用する。ライフタイムにより、ダングリングポインタを防ぎ、メモリ安全性を保証する。

多くの場合、ライフタイムは暗黙的に推論されるが、複数の参照がある場合など、明示的なライフタイム注釈が必要になることがある。

// 明示的なライフタイム注釈
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

let string1 = String::from("long string");
let string2 = String::from("short");
let result = longest(string1.as_str(), string2.as_str());

関連項目:借用とライフタイム借用所有権

ループ

処理を繰り返し実行することをループという。繰り返しを参照。

関連項目:繰り返しloop

予約語

プログラミング言語において特別な意味を持ち、識別子として使用できない語を予約語(キーワード)という。Rustのキーワードは以下の通りである。

as       async    await    break    const    continue crate
dyn      else     enum     extern   false    fn       for
if       impl     in       let      loop     match    mod
move     mut      pub      ref      return   Self     self
static   struct   super    trait    true     type     unsafe
use      where    while

予約語(将来の使用のため):
abstract become   box      do       final    macro    override
priv     typeof   unsized  virtual  yield

バイト

データの基本単位をバイトという。1バイトは8ビットで構成され、0から255までの256通りの値を表現できる。Rustでは、u8型が1バイトを表す。

Cargo

Cargoは、Rustの公式パッケージマネージャおよびビルドシステムである。プロジェクトの作成、依存関係の管理、ビルド、テストの実行などを行う。Cargoを使用することで、Rustプロジェクトの管理が統一的かつ効率的に行える。

cargo new my_project      # 新規プロジェクト作成
cargo build               # ビルド
cargo run                 # ビルドして実行
cargo test                # テスト実行
cargo doc --open          # ドキュメント生成

Copy

Copyトレイトを実装している型は、値がコピーされる(ムーブされない)。整数型、浮動小数点数型、ブール型、文字型など、スタックのみに格納される型はCopyを実装している。

let x = 5;
let y = x;  // コピーされる
println!("{}, {}", x, y);  // 両方とも使用可能

// Copyを実装していない型(String)
let s1 = String::from("hello");
let s2 = s1;  // ムーブされる
// println!("{}", s1);  // エラー

関連項目:クローンムーブ

Option型

Option型は、値が存在するか否かを表す列挙型である。RustにはNULLポインタは存在しない代わりに、値の不在を型安全に表現するためにOption型を使用する。

enum Option<T> {
    Some(T),  // 値が存在
    None,     // 値が存在しない
}

let some_number = Some(5);
let no_number: Option<i32> = None;

// パターンマッチで処理
match some_number {
    Some(n) => println!("値: {}", n),
    None => println!("値なし"),
}

// unwrap_or でデフォルト値を指定
let value = no_number.unwrap_or(0);

関連項目:Result型列挙型

Result型

Result型は、成功または失敗を表す列挙型である。回復可能なエラー処理に使用される。Result型を使用することで、エラーを型システムで表現し、安全に処理できる。

enum Result<T, E> {
    Ok(T),   // 成功時の値
    Err(E),  // エラー時の値
}

use std::fs::File;

// Result型を返す関数
let f = File::open("hello.txt");
match f {
    Ok(file) => println!("ファイルを開きました"),
    Err(error) => println!("エラー: {:?}", error),
}

// ?演算子でエラー伝播
fn read_file() -> Result<String, std::io::Error> {
    let mut contents = String::new();
    File::open("hello.txt")?.read_to_string(&mut contents)?;
    Ok(contents)
}

関連項目:エラーハンドリングOption型?演算子

スマートポインタ

スマートポインタは、ポインタのように動作するが、追加のメタデータと機能を持つデータ構造である。Rustの主なスマートポインタには以下がある。

use std::rc::Rc;

let a = Rc::new(5);
let b = Rc::clone(&a);
let c = Rc::clone(&a);
println!("参照カウント: {}", Rc::strong_count(&a));  // 3

関連項目:ポインタ

実装

実装は、構造体や列挙型に対してメソッドや関連関数を定義することである。implキーワードを使用する。

struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    // メソッド(selfを取る)
    fn area(&self) -> u32 {
        self.width * self.height
    }

    // 関連関数(selfを取らない)
    fn square(size: u32) -> Rectangle {
        Rectangle {
            width: size,
            height: size,
        }
    }
}

let rect = Rectangle { width: 30, height: 50 };
println!("面積: {}", rect.area());
let sq = Rectangle::square(10);

関連項目:トレイト構造体impl


Rustの記号・キーワード等

本セクションでは、Rustで使用される記号とキーワードを解説する。

記号

!

論理否定演算子。ブール値を反転する。また、マクロ呼び出しの識別子としても使用される。

let x = true;
let y = !x;  // false

println!("Hello");  // マクロ呼び出し
vec![1, 2, 3];      // マクロ呼び出し

!=

不等価比較演算子。2つのオペランドが等しくない場合にtrueを返す。

if x != 0 {
    println!("xは0ではない");
}

#

属性の開始を示す記号。#[attribute]の形式で使用する。

#[derive(Debug)]
struct Point { x: i32, y: i32 }

#[test]
fn test_example() {
    assert_eq!(2 + 2, 4);
}

%

剰余演算子。除算の余りを返す。

let remainder = 10 % 3;  // 1

&

参照演算子、ビット単位のAND演算子。参照の作成に使用する。不変借用を表す。

let x = 5;
let r = &x;      // 不変参照

let result = 5 & 3;  // ビットAND: 1

使用例:複数の関数が同時に同じデータを読み取る場合に使用する。

fn print_length(s: &String) {
    println!("{}", s.len());
}
let text = String::from("hello");
print_length(&text); // textの所有権は維持される

よくある誤用:不変参照と可変参照を同時に作成しようとするとコンパイルエラーになる。

let mut s = String::from("hello");
let r1 = &s;
let r2 = &mut s; // エラー:不変借用が存在する間は可変借用できない

&&

論理積演算子。短絡評価を行う。

if x > 0 && y > 0 {
    println!("両方とも正");
}

&mut

可変参照を作成する演算子。可変参照を通じて値の変更が可能だが、同時に存在できる可変参照は1つのみである。

let mut x = 5;
let y = &mut x;
*y += 1;

使用例:関数内でデータを変更する必要があるが、所有権は渡したくない場合に使用する。

fn append_world(s: &mut String) {
    s.push_str(", world");
}
let mut text = String::from("hello");
append_world(&mut text); // textが変更される

よくある誤用:同時に複数の可変参照を作成しようとするとコンパイルエラーになる。

let mut s = String::from("hello");
let r1 = &mut s;
let r2 = &mut s; // エラー:可変借用は同時に1つのみ

'(シングルクォート)

文字リテラルを囲む引用符。また、ライフタイムの注釈にも使用する。

let c: char = 'a';

fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() { x } else { y }
}

()

関数呼び出し、タプルの作成、のグループ化に使用する括弧。

let result = func(x, y);  // 関数呼び出し
let t = (1, 2, 3);        // タプル
let value = (a + b) * c;  // グループ化

*

乗算演算子、参照外し演算子、rawポインタ宣言。

let product = 3 * 4;  // 乗算: 12
let x = 5;
let r = &x;
let y = *r;  // 参照外し: 5

+

加算演算子、トレイト境界の結合。

let sum = 3 + 4;  // 加算: 7

// トレイト境界
fn notify(item: &(impl Display + Clone)) {
    // 処理
}

-

減算演算子、単項マイナス演算子。

let diff = 10 - 3; // 減算: 7 let negative = -x; // 単項マイナス

->

関数の戻り値のを示す記号。

fn add(a: i32, b: i32) -> i32 {
    a + b
}

.

フィールドアクセス、メソッド呼び出し。

let len = vec.len();     // メソッド呼び出し
let name = person.name;  // フィールドアクセス

..

範囲演算子。範囲の指定に使用する。

for i in 0..10 {  // 0から9まで
    println!("{}", i);
}

let slice = &array[1..4];  // インデックス1から3まで

/

除算演算子

let quotient = 7 / 2;  // 整数除算: 3
let quotient = 7.0 / 2.0;  // 浮動小数点除算: 3.5

//

1行コメントの開始を示す記号。

// これはコメント
let x = 10;  // 行末コメント

:

注釈、トレイト境界の区切り。

let x: i32 = 10;  // 型注釈

fn generic<T: Display>(item: T) {  // トレイト境界
    // 処理
}

::

パス区切り記号。モジュール、型、関連関数へのアクセスに使用する。

use std::collections::HashMap;
let v = Vec::new();
String::from("hello");

;

の終了、を文に変換する記号。

let x = 5;  // 文
println!("Hello");  // 式文

let y = {
    let x = 3;
    x + 1  // 式(セミコロンなし):4を返す
};

let z = {
    let x = 3;
    x + 1;  // 文(セミコロンあり):()を返す
};

<

「より小さい」を判定する比較演算子、ジェネリクスの型パラメータ開始。

if x < 100 {
    println!("xは100未満");
}

let vec: Vec<i32> = Vec::new();

<<

左シフト演算子

let result = 1 << 3;  // 8(1を左に3ビットシフト)

<=

「以下」を判定する比較演算子

if x <= 100 {
    println!("xは100以下");
}

==

「等しい」を判定する比較演算子

if x == 0 {
    println!("xは0");
}

=>

match式のアーム、クロージャの本体を示す記号。

match x {
    0 => println!("zero"),
    _ => println!("other"),
}

let add = |a, b| a + b;

>

「より大きい」を判定する比較演算子、ジェネリクスの型パラメータ終了。

if x > 0 {
    println!("xは正");
}

>=

「以上」を判定する比較演算子

if x >= 0 {
    println!("xは0以上");
}

>>

右シフト演算子

let result = 8 >> 2;  // 2(8を右に2ビットシフト)

=

代入演算子、パターンの束縛。

let x = 10;

?

エラー伝播演算子Result型Option型でエラーを呼び出し元に返す。?演算子を使用することで、エラー処理を簡潔に記述できる。

fn read_file() -> Result<String, std::io::Error> {
    let mut contents = String::new();
    File::open("hello.txt")?.read_to_string(&mut contents)?;
    Ok(contents)
}

使用例:複数のエラーを返す可能性のある操作を連鎖させる場合に簡潔に記述できる。

fn process_file() -> Result<String, std::io::Error> {
    let content = std::fs::read_to_string("input.txt")?;
    std::fs::write("output.txt", &content)?;
    Ok(content)
}

よくある誤用?演算子はResultまたはOptionを返す関数内でのみ使用できる。

fn main() {
    let content = std::fs::read_to_string("file.txt")?; // エラー:mainは()を返す
}

@

パターンマッチングでの束縛。値をテストしながら変数に束縛する。

match x {
    n @ 1..=5 => println!("1から5の値: {}", n),
    _ => println!("その他"),
}

[]

配列ベクタのインデックスアクセス、配列リテラル、スライス

let arr = [1, 2, 3, 4, 5];  // 配列リテラル
let item = arr[0];           // インデックスアクセス
let slice = &arr[1..3];      // スライス

\

文字列内でエスケープシーケンスの開始を示す。

let s = "Hello\nWorld";  // 改行
let path = "C:\\Users";  // バックスラッシュ

^

ビット単位のXOR演算子

let result = 5 ^ 3;  // 6(ビットXOR)

_

ワイルドカードパターン、使用しない変数の名前、数値リテラルの区切り。

let _ = some_function();  // 戻り値を無視
match x {
    _ => println!("すべてにマッチ"),
}
let large = 1_000_000;  // 数値の区切り

{}

ブロック、構造体リテラル、マクロのパターンに使用する括弧。

{
    // ブロック
    let x = 5;
}

let person = Person { name: "Alice", age: 30 };  // 構造体リテラル

|

ビット単位のOR演算子、クロージャのパラメータ区切り、パターンの選択。

let result = 5 | 3;  // 7(ビットOR)

let add = |a, b| a + b;  // クロージャ

match x {
    1 | 2 | 3 => println!("1、2、または3"),
    _ => println!("その他"),
}

||

論理和演算子。短絡評価を行う。

if x == 0 || y == 0 {
    println!("どちらかがゼロ");
}

+= -= *= /= %=

複合代入演算子。演算と代入を同時に行う。

let mut x = 10;
x += 1;   // x = x + 1 と同等
x *= 2;   // x = x * 2 と同等

"(ダブルクォート)

文字列リテラルを囲む引用符。

let s = "Hello, world!";

英字(アルファベット順)

abs()

数値の絶対値を返すメソッド。整数型および浮動小数点数型で提供される。

let x = -10;
let y = x.abs();  // 10

let z = -3.14_f64;
let w = z.abs();  // 3.14

as

型変換(キャスト)、トレイト実装の明示、use時の別名指定に使用するキーワード。

let x = 5u32;
let y = x as f64;  // 型変換

use std::io::Result as IoResult;  // 別名

assert! / assert_eq!

条件が真であることを確認するマクロ。テストやデバッグに使用する。

assert!(x > 0, "xは正の数でなければならない");
assert_eq!(2 + 2, 4);
assert_ne!(x, y);

async / await

非同期処理のためのキーワード。asyncで非同期関数を定義し、awaitで非同期処理の完了を待つ。

async fn fetch_data() -> Result<String, Error> {
    let response = http_get("url").await?;
    Ok(response)
}

break

ループを中断するキーワード。値を返すこともできる。

let result = loop {
    counter += 1;
    if counter == 10 {
        break counter * 2;  // 値を返してループ終了
    }
};

const

定数を定義するキーワード。コンパイル時に評価される。

const MAX_POINTS: u32 = 100_000;
const PI: f64 = 3.141592653589793;

continue

ループの次の反復に移るキーワード。現在の反復の残りの処理をスキップする。

for i in 0..10 {
    if i % 2 == 0 {
        continue;  // 偶数はスキップ
    }
    println!("{}", i);
}

crate

現在のクレートのルートを表すキーワード。パスの開始点として使用する。

use crate::my_module::my_function;

else

if式で条件がの場合の処理を示すキーワード。

let number = if condition { 5 } else { 6 };

enum

列挙型を定義するキーワード。

enum Color {
    Red,
    Green,
    Blue,
}

fn

関数を定義するキーワード。

fn add(a: i32, b: i32) -> i32 {
    a + b
}

for

イテレータの要素を順に処理する繰り返し文のキーワード。

for item in collection {
    println!("{}", item);
}

for i in 0..10 {
    println!("{}", i);
}

if

条件分岐のキーワード。条件がの場合に処理を実行する。Rustでは、if式は値を返す。

if x > 0 {
    println!("正の数");
} else if x == 0 {
    println!("ゼロ");
} else {
    println!("負の数");
}

let number = if condition { 5 } else { 6 };

impl

実装を定義するキーワード。構造体や列挙型にメソッドを実装する。

impl Rectangle {
    fn area(&self) -> u32 {
        self.width * self.height
    }
}

impl Display for Person {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{}", self.name)
    }
}

let

変数を宣言するキーワード。

let x = 5;
let mut y = 10;
let (a, b) = (1, 2);

使用例:変数はデフォルトで不変であり、意図しない変更を防ぐ。

let x = 5;
// x = 6; // エラー:不変変数に再代入できない
let mut y = 5;
y = 6; // OK:mutを付けると可変になる

よくある誤用:変数のシャドーイング(同名の新しい変数宣言)と再代入を混同する。

let x = 5;
let x = x + 1; // OK:シャドーイング(新しい変数)
let mut y = 5;
y = y + 1; // OK:再代入

loop

無限ループを作成するキーワード。breakで終了する。

loop {
    println!("無限ループ");
    if condition {
        break;
    }
}

let result = loop {
    counter += 1;
    if counter == 10 {
        break counter * 2;  // 値を返す
    }
};

match

パターンマッチングのキーワード。値のパターンに基づいて分岐する。すべてのパターンを網羅する必要がある。matchを使用することで、すべてのケースを処理することが保証され、バグを減らすことができる。

match value {
    0 => println!("zero"),
    1 | 2 => println!("one or two"),
    3..=9 => println!("three to nine"),
    _ => println!("other"),
}

let result = match some_option {
    Some(x) => x,
    None => 0,
};

使用例:全てのケースを網羅する必要があるため、エラーハンドリングに最適である。

let result: Result<i32, &str> = Ok(42);
match result {
    Ok(value) => println!("成功: {}", value),
    Err(e) => println!("エラー: {}", e),
}

よくある誤用:全てのパターンを網羅しないとコンパイルエラーになる。

match some_option {
    Some(x) => println!("{}", x),
    // エラー:Noneケースが不足している
}

mod

モジュールを定義するキーワード。

mod my_module {
    pub fn public_function() {
        println!("公開関数");
    }
}

move

クロージャがキャプチャした変数の所有権を取得するキーワード。スレッド間でデータを移動する際に必要となる。

let v = vec![1, 2, 3];
thread::spawn(move || {
    println!("{:?}", v);
});

使用例:スレッドに変数を渡す場合、所有権を移動させる必要がある。

let data = vec![1, 2, 3];
thread::spawn(move || {
    // dataの所有権がこのスレッドに移動
    println!("{:?}", data);
});
// println!("{:?}", data); // エラー:dataの所有権は移動済み

よくある誤用moveを付けずにスレッドで外部変数を使用するとコンパイルエラーになる。

let v = vec![1, 2, 3];
thread::spawn(|| {
    println!("{:?}", v); // エラー:vの生存期間が不明
});

mut

変数や参照をミュータブル(変更可能)にするキーワード。

let mut x = 5;
x = 6;  // OK

let y = 10;
let r = &mut y;  // 可変参照

panic!

回復不可能なエラーを発生させるマクロ。プログラムを即座に終了する。

if x < 0 {
    panic!("xは負の数であってはならない");
}

println!

標準出力に改行付きで出力するマクロ。

println!("Hello, world!");
println!("{}は{}歳です", name, age);
println!("{:?}", vec);  // デバッグ出力

pub

アイテムを公開するキーワード。他のモジュールからアクセス可能にする。

pub struct Point {
    pub x: i32,
    pub y: i32,
}

pub fn public_function() {
    // 処理
}

return

関数から値を返すキーワード。最後の式はreturnなしで返すことができる。

fn add(a: i32, b: i32) -> i32 {
    return a + b;  // 明示的なreturn
}

fn multiply(a: i32, b: i32) -> i32 {
    a * b  // 最後の式が戻り値
}

self / Self

self:メソッドの第1パラメータで、インスタンス自身を表す。Self:現在の型を表す。

impl Rectangle {
    fn area(&self) -> u32 {  // selfはインスタンス
        self.width * self.height
    }

    fn square(size: u32) -> Self {  // Selfは型
        Self {
            width: size,
            height: size,
        }
    }
}

static

静的変数を定義するキーワード。プログラムの実行期間中、固定されたメモリアドレスを持つ。

static HELLO: &str = "Hello, world!";
static mut COUNTER: u32 = 0;  // 可変静的変数(unsafeが必要)

struct

構造体を定義するキーワード。

struct Person {
    name: String,
    age: u32,
}

trait

トレイトを定義するキーワード。

trait Summary {
    fn summarize(&self) -> String;
}

true / false

ブール型のを表すリテラル。

let t = true;
let f = false;

type

型エイリアスを定義するキーワード。

type Kilometers = i32;
type Result<T> = std::result::Result<T, std::io::Error>;

unsafe

安全性チェックを無効化するキーワード。以下の操作に必要である。

unsafe {
    let r = 0x012345usize as *const i32;
    println!("{}", *r);  // rawポインタの参照外し
}

use

パスをスコープに導入するキーワード。モジュールや型を簡潔に参照できる。

use std::collections::HashMap;
use std::io::{self, Write};

vec!

ベクタを作成するマクロ。

let v = vec![1, 2, 3, 4, 5];
let zeros = vec![0; 100];  // 100個の0

where

トレイト境界を指定するキーワード。複雑な境界を読みやすく記述できる。

fn some_function<T, U>(t: &T, u: &U) -> i32
where
    T: Display + Clone,
    U: Clone + Debug,
{
    // 処理
}

while

条件がの間、処理を繰り返すキーワード。

let mut count = 0;
    while count < 10 {
    println!("{}", count);
    count += 1;
}

索引

あ行

か行

さ行

た行

は行

ま行

ら行

や行

わ行