この記事は、Marc Brooker氏によって2020年3月に公開された「Two Years With Rust」の翻訳転載です。著者の許可を得て配信しています。
私がRustを学び始めてからちょうど2年以上が経ちました。それ以来、Firecracker コードベースや他の多くのプロジェクトでの作業を含め、本業ではRustを多用してきました。Rustは、ここ数年行ってきたシステムレベルの仕事にとても適しています。パフォーマンスもよく、密度が高く、繊細で、常にセキュリティ面でもセンシティブです。タイプシステム、オブジェクトライフサイクル、スレッドモデルは、この種の作業に適していて、かなり直感的だと思います。ほとんどの人がそうであるように、私も時々コンパイラと喧嘩をすることがありますが、今はほとんど喧嘩もなく、仲良くやっています。
Rust は、私がよく使う数値シミュレータのような、パフォーマンスを重視した小さなプログラムを書くための言語として、とても便利な Go に取って代わられました。Go は C 言語に取って代わり、日々の役に立つツールとして R と Python の仲間入りをしました。私は今でもRustのプログラムを書くのにGoよりも多くの時間を費やし、Cよりも多くの時間を費やしていることに気付きました(Cがまともなデータ構造やストリング処理がないことで食い止められている場合を除いて)。また、プログラムは最初の実行で動作する可能性が高いこともわかりましたが、それを定量化する努力はしていません。
これまでの私のキャリアでは、C, C++, Java, Python, Ruby, Go, Rust, Scheme, Basic, Perl, Bash, TLA+, Delphi, Matlab, ARM and x86 assembly, R (これ以外にも習ったけれど、書き忘れてしまっているものもあるかもしれません)で給料をもらって仕事をしてきました。これらの言語で書かれた私のコードのいくつかが、まだどこかで機能しているかもしれません。他の言語もたくさん学んできました。言語を学ぶのが好きだからです。例えば、最近はFrinkを使って遊んでいます。私は言語については自由な発想を持っている方だと思います。
しかし、場合によっては、私は自分の同僚やチームを特定の選択肢からは遠ざけるようにしています。例えば、CやC++は、危険なメモリ安全バグを回避するやり方で使用するのは難しく、コストもかかるようです。ユーザーにとってこれらのバグが重要であるなら、自分のコードをより深く学ぶ必要があります。優れた安全な C 言語を書くことは可能ですが、そこに至るまでには、ツールと、ひたむきに頑張る謙虚さとの両方が必要になります。Rust は万能薬ではありません。ただ以前はかなり貧弱だったのにも関わらず、今は本当に良い代替手段となっています。小さなコマンドラインプログラム、高性能なサービス、システムレベルのコードにRustをお勧めしているし、自分でもRustを選んで使っています。
私がRustを好きな理由についてお話します。世の中には優れたプログラミング言語がたくさんあります。Rustの大まかな解説とエコシステムの中での位置づけに合うものが複数あります。実際に解決すべき問題を抱えていて、とても優れています。私は、Rustが必ずしも、最近接より技術的に優れているとは確信していませんが、Rustが他のものよりも突出して優れている点がいくつかあります。
コンパイラのエラーメッセージが親しみやすく、すごく役に立つので気に入っています。フリーの本や標準ライブラリのドキュメントはとても分かりやすいです。タイプシステムは作業しやすくて優れています。ビルドインのツール (rustup, cargoとその関連ツール) は簡単で強力です。標準的な書式設定ツールは、コードベースを整然とした状態に保ち、自転車置き場をペンキで塗らないようにするために長い道のりを歩んでいます。スタティックリンクとクロスコンパイルがビルドインされています。機能的なイディオムが散りばめられていて、パワーがあり表現力が豊かだと思います。(マクロのように)曖昧なコードになる機能はお勧めしません。すぐに使えるというところは非常に素晴らしいです。Fearless Concurrency は実際にそれを実現しています。
他にもたくさんあります。
Rustがあまり人気がない原因は何なのでしょうか? 私も実際Rustに関しては、好きなところばかりではありません。嫌いなポイントとしては、短期的なものがあることです。async と await が安定する前の 1 年ほどの間に Rust で async ネットワーキング コードの書き方を学びました。一貫性のないドキュメントと壊れた API のせいで、とてもいらいらしました。コンパイラは、ループのアンロールや自動ベクトル化などの最適化については、C コンパイラほどスマートにこなせません (安全チェックやその他の Rust 固有のオーバーヘッドを省略するという素晴らしい仕事をしていますが)。仕様のいくつかの部分、例えばエイリアシングルールやアトミックメモリの順序の正確な設定は、私の理想よりもまだ少し曖昧です。スタティック解析ツールはまだ先の話です。アラインメントされたメモリの割り当ては、特に標準データ構造のいくつかを使用したい場合には大変です。このように難点もいくつかあります。
それぞれのケースで、細かい点を見るたびに状況が改善されているように感じます。コミュニティは大きな進歩を遂げているように見えます。asyncとawaitはとりわけ、大人気です。
私の中での最大の長期的な問題は、unsafe(アンセーフ)ではないということです。Rustは、コードのセクションを安全でないとマークされるようにするために、非常に合理的な決定をしているように見えます。これにより、メモリやライフサイクルの保証の範囲外に色をつけることができるようになりました。その名の通り、アンセーフコードは安全でない傾向があります。安全でないコードの大きな問題は、ブロック内のコードが安全でないということではなく、安全なコードの安全性を、微妙で目立たない方法で壊してしまうことです。何千行も離れた安全なコードであっても、安全ではないのです。このような遠隔作用が起こるので、アンセーフコードを含むコードベースの特性について推論するのは難しくなります。低レベルのシステムコードの場合は、おそらくそれがすべてでしょう。
こういったことは、コミュニティにとっては驚きではありません。Rust コミュニティは、アンセーフであることに対してのコストとメリットについて非常に現実的にとらえています。時々その議論は行き過ぎてしまうこともありますが(Steve Klabnik氏が書いているように)、ほとんどの場合、相対的な部外者である私にはそれが健全な精神から来る健全な議論であるように思えます。
問題は、この不気味なアンセーフなビヘイビアは、新しいRustプログラマーには明確ではない傾向があるということです。私自身を含め、ほとんどの人が始めるのを見てきたメンタルモデルは、アンセーフブロックはその中のものを壊す可能性があるので、コードをうまく書くためには注意が必要だということです。ただ残念ながら、それだけでは十分ではありません。
より優れたスタティックとより優れたダイナミックな解析ツールは、ここでも役立つでしょう。それはコンパイラからのよりベターな支援や、安全でないものを使用する代替手段と同様です。システム言語としてのRustの長期的な成功は、コミュニティやツールがどれだけ上手く安全でないものを扱うかにかかっていると思います。Rustの価値の多くはその安全性にあり、知らないうちにその安全性を壊すのは簡単です。
もう一つの長期的なリスクは言語の大きさです。私が最後に毎日C++を使って仕事をし始めてから10年以上が経ちましたが、もうC++プログラマーとしての実力はどこにもありません。その理由の一つは、C++が進化してきたからです。まぁそれはいいことなのですが。もう一つの理由は、C++が巨大だからです。10年という年数を考えても、有能なパートタイム C++ プログラマーになるのは難しいように思えます。ものすごく熱中しないと、全てを頭に叩き込むことはできません。Rustも同じかもしれませんが、それは本当に残念なことだと思います。