Rustチュートリアル

目次

1. はじめに

Rustは、高速で信頼性が高く、生産性の高いシステムプログラミング言語です。メモリ安全性とスレッド安全性を保証しながら、高性能なアプリケーションを構築することができます。

2. インストール

Rustをインストールするには、公式サイトからRustupをダウンロードし、指示に従ってインストールします。以下のコマンドで、Rustのバージョンを確認できます:

$ rustc --version

3. Hello, World!

最初のRustプログラムを作成しましょう。以下のコードをmain.rsというファイル名で保存します:

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

コンパイルして実行するには:

$ rustc main.rs
$ ./main
Hello, World!

4. 変数と可変性

Rustでは、デフォルトで変数は不変です。可変にするにはmutキーワードを使用します:

let x = 5; // 不変
let mut y = 5; // 可変
y = 6; // OK

5. データ型

Rustは静的型付け言語です。主な型には以下があります:

6. 関数

関数はfnキーワードで定義します:

fn add(x: i32, y: i32) -> i32 {
    x + y
}

fn main() {
    let result = add(5, 3);
    println!("The result is: {}", result);
}

7. 制御フロー

Rustは一般的な制御フロー構文をサポートしています:

// if式
let number = 6;
if number % 2 == 0 {
    println!("偶数です");
} else {
    println!("奇数です");
}

// ループ
for i in 0..5 {
    println!("{}回目", i + 1);
}

// while
let mut n = 0;
while n < 5 {
    println!("{}回目", n + 1);
    n += 1;
}

8. 所有権

Rustの特徴的な概念である所有権は、メモリ管理を安全に行うための仕組みです:

fn main() {
    let s1 = String::from("hello");
    let s2 = s1; // s1の所有権がs2に移動
    // println!("{}", s1); // エラー:s1は既に無効
    println!("{}", s2); // OK
}

9. 借用

借用(borrowing)は、所有権を移動せずに一時的に値を参照する方法です。

fn main() {
    let s1 = String::from("hello");
    let len = calculate_length(&s1);
    println!("The length of '{}' is {}.", s1, len);
}

fn calculate_length(s: &String) -> usize {
    s.len()
}

可変な借用も可能ですが、同時に1つの可変な借用しか存在できません:

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

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

10. 列挙型

列挙型(enum)は、複数の異なる値を持つ可能性がある型を定義します。

enum Result<T, E> {
    Ok(T),
    Err(E),
}

enum Direction {
    North,
    South,
    East,
    West,
}

fn main() {
    let result: Result<i32, String> = Result::Ok(42);
    let direction = Direction::North;
}

11. 構造体

構造体(struct)は、関連するデータをグループ化するためのカスタムデータ型です。

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

fn main() {
    let person = Person {
        name: String::from("Alice"),
        age: 30,
    };
    
    println!("{} is {} years old.", person.name, person.age);
}

12. パターンマッチング

パターンマッチングは、Rustの強力な機能の1つで、データの構造に基づいてコードを分岐させることができます。

enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter,
}

fn value_in_cents(coin: Coin) -> u8 {
    match coin {
        Coin::Penny => 1,
        Coin::Nickel => 5,
        Coin::Dime => 10,
        Coin::Quarter => 25,
    }
}

fn main() {
    let coin = Coin::Dime;
    println!("The value is {} cents", value_in_cents(coin));
    
    let number = Some(7);
    match number {
        Some(i) => println!("The value is {}", i),
        None => println!("There is no value"),
    }
}

13. 例外処理

Rustは例外を使用せず、Result型とパニックを使用してエラーを処理します。

use std::fs::File;
use std::io::ErrorKind;

fn main() {
    let f = File::open("hello.txt");

    let f = match f {
        Ok(file) => file,
        Err(error) => match error.kind() {
            ErrorKind::NotFound => match File::create("hello.txt") {
                Ok(fc) => fc,
                Err(e) => panic!("Problem creating the file: {:?}", e),
            },
            other_error => {
                panic!("Problem opening the file: {:?}", other_error)
            }
        },
    };
}

?演算子を使用して、エラー処理をより簡潔に書くこともできます:

use std::fs::File;
use std::io;
use std::io::Read;

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

14. モジュール

モジュールはコードを整理し、再利用性を高めるのに役立ちます。

mod front_of_house {
    pub mod hosting {
        pub fn add_to_waitlist() {}
    }
}

use crate::front_of_house::hosting;

pub fn eat_at_restaurant() {
    hosting::add_to_waitlist();
}

15. クレート

クレートはRustのコードパッケージです。ライブラリクレートと実行可能クレートの2種類があります。

外部クレートを使用するには、Cargo.tomlファイルに依存関係を追加します:

[dependencies]
rand = "0.8.3"

そして、コードで使用します:

use rand::Rng;

fn main() {
    let secret_number = rand::thread_rng().gen_range(1..101);
    println!("The secret number is: {}", secret_number);
}