21 ポイント 投稿者 tsboard 2024-07-24 | 5件のコメント | WhatsAppで共有

Rustを使い始めておよそ10年になり、この言語を本当に愛しています。ですが、いくつかがっかりする点もあります。以下がその一覧です。

1. Result<T, E>の問題

Rustのエラー処理が明確で強制的である点は素晴らしいです。しかし実際に使ってみると、不便な点も多くあります。

  • ライブラリ作成者の難しさ: 新しいエラー型を作って変換する過程が煩雑です。依存関係を追加するたびに、各関数のエラー型をラッパーエラー型に追加する作業は特に面倒です。
  • アプリケーションコードの煩雑さ: 関数がなぜ失敗したかよりも、エラーを上位へ伝播してユーザーに結果を見せることのほうが重要です。Javaと違ってRustは伝播の過程でバックトレースを提供しないため、問題の原因を把握しにくいです。

2. モジュールシステムの柔軟性

Rustのモジュールシステムは柔軟すぎて、かえって不便なことがよくあります。

  • 過度な柔軟性: 型を再エクスポートしたりアクセスレベルを細かく調整したりできますが、そのせいで意図しない型を誤って公開してしまうことがあります。
  • 孤児規則の問題: プロジェクトを複数のクレートに分けることが推奨されますが、孤児規則がときどき妨げになります。

3. コンパイル時間とIDEツール

Rustのコンパイル時間とIDEツールのエラーチェックは遅すぎます。

  • 長いコンパイル時間: 大規模プロジェクトでは、1つの関数を修正するとクレート全体が再コンパイルされてしまい、非常に非効率です。
  • 遅いIDEの応答速度: Rust analyzerは、タイピングするたびにプロジェクトを再インデックスしているかのように感じられ、大規模プロジェクトでは特に問題になります。

結論

Rustは私が最も好きな言語ですが、このようながっかりする点も存在します。他のユーザーも同じ問題を経験しているのか気になります。

5件のコメント

 
ranolp 2024-07-28

エラー処理については、ライブラリでは snafu / thiserror、アプリケーションでは eyre / anyhow を導入して使うと便利になります

 
y15un 2024-07-26

ライブラリ作者の難しさ: [..snip..] 依存関係を追加するたびに、各関数のエラー型をラッパー用のエラー型に追加する作業はとりわけ面倒です。

この部分には本当に痛いほど共感します。クレート専用のエラー enum を作って、依存先から引っ張ってくるエラー型のために毎回 impl From<ExtError> for Error を書きながら、「面倒くさくてたまらないな」と思ったことが一度や二度ではありません……

 
eususu 2024-07-26

まだちゃんと始められていないからか、こういう失望を感じてみたいですね。
良い記事をありがとうございます〜

 
undercat 2024-07-25

良い記事をありがとうございます!

 
tsboard 2024-07-24

コンパイル時間が長い件については、以下のコメントが参考になると思ったので追記します: (by pr4wl)

Rust analyzer が変更のたびに長い再コンパイルを実行しているなら、おそらくアプリケーションのビルド時に使っている機能や環境変数が異なることが原因です。デフォルトでは、RA はビルド成果物を保存するために cargo build と同じターゲットディレクトリを使用しており、互換性のないビルドを行うと、何度もフルビルドが走ることになります。

この問題は、特に Bevy でビルドには bevy/dynamic_linking 機能を使っているのに、Rust analyzer では使っていない場合によく発生します。

最も簡単な解決方法は、RA に別のターゲットディレクトリを使うよう指示することです。これに関する詳しい内容は rust-analyzer.cargo.targetDir を確認してください。

もう 1 つの解決方法は、すべての機能と環境変数を同じに設定して、お互いのビルド成果物を再利用できるようにすることです。ただし、これは面倒な場合があります。