⚙️

なぜ Rust が好きなのか

2024/12/01に公開

さすが Rust! おれたちにできないメモリ管理を平然とやってのける そこにシビれる! あこがれるゥ!

この味は! ………コンパイルが通らない「味」だぜ……

はじめに

筆者は個人的興味から(実務ではないが)Rust を書いており,とても好きな言語である.

Rust は難易度が高いと言われることが多く,他の言語と比較すると採用されている場面も少ないため情報も少ない.しかし,Rust を書いているときに感じる楽しさや面白さは他の言語にはないものがある.

せっかくなので,Rust が好きな理由をまとめてみたい.

Rust の特徴

Rust には他の言語にはない概念として,例えば以下のようなものがある.

  • 所有権

  • 借用

  • トレイト

Rust は総じてメモリ管理が厳しく所有権の誤用,無効な参照,メモリリークなどのリスクをコンパイル時に検出することができる.

所有権

Rust において,各値は必ず所有者(変数)を持つ.例えば,以下のコードを見てみよう.このコードはコンパイル時にエラーが発生する.

fn main() {
    let s = String::from("hello");

    // sの所有権がs1に移動する
    let s1 = s;
    let s2 = s; // エラー Value used after being moved [E0382]
}

このコードは,String 型の s という変数を宣言し,"hello" という文字列を代入している.

次に,s1s の所有権を移動している.このとき,s の所有権は s1 に移動するため,s は使用できなくなる.

このように,Rust では所有権の移動が厳密に制限されているため,メモリリークや二重解放などの問題をコンパイル時に検出することができる.

借用

Rust では,所有権を移動せずに値を参照することができる.これを借用と呼ぶ.

例えば,以下のコードを見てみよう.上記のコードを修正したものである.

fn main() {
    let s = String::from("hello");

    let s1 = &s;
    let s2 = s;
}

& 演算子を使うことで,s の所有権を移動せずに参照を作成することができる.このように,Rust では所有権を移動せずに値を参照することができるため,複数の箇所で同じ値を参照する場合に便利である.

Rust では所有権と借用が明確に区別されており,所有権の移動や借用のルールが厳密に適用される.始めは&をつけたり外したりしてしまうが,参照と値を使い分けることに慣れると徐々にスムーズに書けるようになる.

トレイト

Rust にはトレイトという概念がある.トレイトは他の言語でいうインターフェースや抽象クラスに似たもので,振る舞いを定義するためのものである.構造体や列挙型にトレイトを実装することで,その振る舞いを共通化することができる.

例えば,以下のコードを見てみよう.

trait Animal {
    fn sound(&self);
}

struct Cat;

impl Animal for Cat {
    fn sound(&self) {
        println!("Meow");
    }
}

struct Dog;

impl Animal for Dog {
    fn sound(&self) {
        println!("Woof");
    }
}

fn main() {
    let cat = Cat;
    let dog = Dog;

    cat.sound();
    dog.sound();
}

このコードは,Animal というトレイトを定義し,CatDog という構造体に Animal トレイトを実装している.

これの何がいいかというと,例えば Animal トレイトを実装した構造体を引数に取る関数を定義することで,CatDog という異なる構造体に対して同じ関数を適用することができる.やっていることは他の言語のクラスに似ている.

クラスの場合は共通の処理を実装した抽象クラスを継承して使用する形となる.この場合,Cat などのクラスのインスタンスで処理するため実行時にコスト(メモリや処理速度)がかかる.

一方で Rust のトレイトはコンパイル時に解決されるため,実行時のコストがなく高速な動作となる.

これを静的ディスパッチと呼び,Rust の特徴の一つである「ゼロコスト抽象化(実行時にコストが増加しない)」の一例とされる(正直このあたりはイマイチよくわかっていない感がある).

これらの例を見ると,Rust が他の言語と比べてどういった特徴を持っているかがわかるものの難易度が高そうなイメージを抱くのではないだろうか.

Rust は優しい言語である

しかし,Rust は難しい言語であると同時に,とても優しい言語でもある.

Rust はコンパイラが非常に賢く,コンパイル時にエラーを出してくれるため実行時にバグが起きることが少ない.動かしてみて想定した結果にならない場合は開発者のロジックが誤っていることがほとんどであり,コードの書き方が間違っていることは少ない.

Rust を書いているととにかくコンパイルが通らない.これはストレスに感じることもあるが,開発者がリスクのあるコードを書かないようにしてくれているとも言える.他の言語で実装する場合に,メモリリークや無効な参照などを考慮してコードを書く必要があるが,毎回できていると言えるだろうか(言えない).Rust の場合はコンパイラがそれを検出してくれるため,開発者はその心配をしなくてもよい.これは Rust の優しさである.

ただ,コード自体も使いやすい強力なものが揃っており,パターンマッチングの構文や「?」を用いたエラーハンドリングなど,使ってみると便利さに驚くことも多い.エラーメッセージも非常にわかりやすく,問題の箇所や原因が明確に記載されているためどこを修正すればよいかがすぐにわかる.

また,慣れてくると Rust のコードは読みやすい.Rust は型定義が厳密であるため,関数の引数や戻り値の型が明確になる.そのため,関数の使い方や戻り値の型がわからないということが少ない.コードを見て得られる情報量が多いため「見ただけで何をしているかわかる」場合が多い.他の言語では変数名に頼ったりコメントの追加が必要な場面でも,Rust ではコード自体が説明書となることが多い.

例えば以下のコードを見てみよう.Rectangle 構造体には area メソッドと can_hold メソッドが定義されている.これらのメソッドは名前や引数,戻り値を見ればおおよその意味が掴めるだろう.

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

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

    fn can_hold(&self, other: &Rectangle) -> bool {
        self.width > other.width && self.height > other.height
    }
}

つまり,Rust は開発者をサポートしてくれる言語なのだ.他の言語では開発者の技術力がそのままコードの品質に直結する一方,Rust ではコンパイラが開発者をサポートしてくれるため,開発者の技術力のみに依存せずに安全なコードを書くことができる.

Rust で開発する場合は「Rust を使いこなす」ではなく「Rust と共同で開発を進める」という感覚である.

難しいこと・新しいことに挑戦するのは楽しい

Rust を書いていると,確かに難しいことが多い.他の言語ではすぐに実装できる処理でも Rust では時間がかかることがある.

しかし,書いているうちに Rust の特徴や概念が理解できるようになり,その過程が楽しい.筆者は Rust は言語というより思想や概念であると感じている.新しいことを知るのは楽しいし,理解できなかったことが理解できるようになると嬉しい.

最近は Rust の情報も増えてきており,生成 AI から情報を得ることも可能だ.筆者はコンパイルエラーの内容や解決方法を調べる際に積極的に活用している.豊富なサンプルコードと解説があり,ドキュメントと併用すれば Rust の学習には非常に有用である.解説を読んでもよくわからない場合に追加で質問できる点も便利だ.

Rust の場合は適当に書くとコンパイルが通らないため,ある程度文法や特徴を把握してから書く必要がある.そのため,他の言語のように「適当になにか作ってみる」ということが難しい.Rust の学習は他の言語とは異なる方向性で向かう必要がありそうだ.筆者もどのように進めるのが良いのか手探りであるが,何らかの講座を作りたいと考えている.

まとめ

Rust は難しい言語であると同時に,とても優しい言語でもある.

簡単には動かないが,そもそもリスクのあるコードを動かすよりも動かす前にエラーを検出できたほうが効率的である.

始めは難しい言語だと感じたが,書いているうちに Rust の特徴や概念が理解できるようになってくると楽しくなってくる.「Rust を協力して開発を進める感覚」は他の言語ではなかなか得られない.

オススメするかと言うと手放しにはオススメできないが,私は Rust が好きだし刺さる人には刺さる言語だと思う.気になった人は触ってみてほしい.実務の仕事が何であれ,自分の好きな技術に触れる時間は大切なものである.

そうだな…わたしは「結果」だけを求めてはいない.「結果」だけを求めていると人は近道をしたがるものだ…近道した時真実を見失うかもしれない.やる気も次第に失せていく.大切なのは「好きな技術に触れようとする意志」だと思っている.向かおうとする意志さえあればたとえ今回はプロジェクトが他の技術だったとしてもいつかはたどり着くだろう?向かっているわけだからな…違うかい?

以上だ( `・ω・)b

GitHubで編集を提案

Discussion