スキップしてメイン コンテンツに移動

Rustは変数の型を省略することが多い


Rustは let x = (1..10).collect(); のように型を省略して書くことが多く、ソースコード上だけでは実際の型が分かりにくい場面が多々あります。
C言語のようにすべての変数の型を明示的に宣言するスタイル(uint32_t x = 0; など)に慣れていると、ソースコード上で型が可視化されていないのは不安に感じるかもしれません。

一見するとスクリプト言語のように見えますが、RustはCやC++以上に厳密な静的型付け言語です。この仕様は欠陥というよりも、「冗長な記述の削減」と「コンパイラの強力な解析」を組み合わせた型推論(Type Inference)という意図的な設計方針によるものです。

Rustのコンパイラは、前後の文脈からパズルを解くように型を確定させます。

  • 冗長な記述の省略: 例えば let mut buffer = Vec::new(); と書き、数行後に buffer.push(10_u32); とデータを追加した場合、コンパイラは「このバッファは32ビット符号なし整数の配列以外あり得ない」と逆算して確定させます。長い型名を何度も書く視覚的ノイズを減らす効果があります。

  • 曖昧さの厳格な排除: もし推論の結果が複数考えられる(曖昧さが残る)場合は、コンパイラが即座にエラーを吐き、プログラマに型の明示を強制します。型がうやむやなまま実行ファイルが生成される危険性はゼロです。

つまり、機械(コンパイラ)にとっては型が完全に自明で安全性が100%担保されているのですが、人間がプレーンなテキストエディタで読む際にだけ「文脈から脳内で推論しなければならない」という負荷がかかるトレードオフが存在します。

最近のプログラミング言語は「エディタ(LSP)の支援があること」を前提に、人間のタイピング量と長すぎる型名のノイズを減らす方向に進化しています。そのため、プレーンなVimでコードを追う際に「人間にとって型が分かりにくい」と感じるのは、非常にまっとうな視点です。

なお、Rustでも型推論に頼る必要はなく、すべての変数に自分で型を明示して書くことも完全に許可されています。

コメント

このブログの人気の投稿

Rustで変数の型を明示的に指定する方法

Rustでは、変数名の後ろに : 型名 を付与することで、すべての変数の型を明示的に指定できます。 Rust // C言語: uint32_t count = 0; let count: u32 = 0 ; // C言語: int32_t offset = -10; let offset: i32 = - 10 ; Rustはデフォルトで変数が「変更不可(イミュータブル)」となるため、後から値を変更(再代入)したい場合は mut キーワードを付けます。 Rust // C言語: size_t index = 0; let mut index: usize = 0 ; index = 1 ; // mutがあるので変更可能 主なプリミティブ型とC言語の対応 ハードウェアに近い制御や厳密なデータ管理が求められる場面では、ビット幅を明示した型指定が多用されます。 u8 , u16 , u32 , u64 : 符号なし整数( uint8_t 等に相当) i8 , i16 , i32 , i64 : 符号付き整数( int8_t 等に相当) usize : メモリアドレスのサイズ(ポインタ長)に依存する符号なし整数( size_t に相当) isize : ポインタ長に依存する符号付き整数( ptrdiff_t に相当) f32 , f64 : 浮動小数点数( float , double に相当) 型の明示が「必須」となる場面 関数内のローカル変数は型を省略(推論)することが許可されていますが、 関数のインターフェース(引数と戻り値) および 定数 については、言語仕様として型の明示が強制されます。 Rust // 引数 (a, b) と戻り値 (-> u32) は型の明示が必須 fn calculate_offset (base: u32 , offset: u32 ) -> u32 { base + offset } // 定数 (const / static) も型の明示が必須 const BASE_ADDRESS: u32 = 0xA0000 ; すべてのローカル変数に型を明示する方針でコードを書けば、LSPの支援がないプレーンなVim上でも、C言語と同等の厳密な可読性を維持したまま開発を進め...