はじめに
Python の学習を始めたときに出てきた 「未使用変数」
「ループ変数を使わないときに _ で書けるって、めっちゃ便利じゃん!」と思ったのが感動でした。
色々調べていくうちに、実は Java 11 からラムダ式でも _ が導入されていることを知りました。
「これは知らなかった…!」という方も多いのではないでしょうか。
そこでこの記事では、Java 11 の _ を中心に、Python や他の言語における未使用変数の扱いを比較しながら解説していきます。
この記事でわかること
- Java における _ の歴史(Java 8まで / Java 9 / Java 11以降)
- ラムダ式で未使用パラメータに _ を使う方法
- Python との違い(慣習か、仕様か)
- 他言語(Go, Rust, Kotlin, Swiftなど)での _ の扱い
- 実務でのベストプラクティス
Javaにおける _ の変遷
1. Java 8まで
Java 8 までは _ はただの変数名として利用できました。
int _ = 10;
System.out.println(_); // 10
特別な意味はなく、未使用変数として _ を使うこともできましたが、読みやすさの観点から推奨されてはいませんでした。
2. Java 9で予約語に
Java 9 から _ は 予約語 となり、変数名として使えなくなりました。
int _ = 10; // コンパイルエラー(Java 9以降)
これは将来的に _ を特別な用途に利用するための布石でした。
3. Java 11での追加 ― ラムダ式の未使用パラメータ
Java 11 で _ が新しい意味を持ちました。ラムダ式で未使用パラメータを表すために _ が利用できるようになったのです。
従来は未使用の引数に適当な名前を付けていました。
// 従来
BiConsumer<String, Integer> printer = (s, unused) -> System.out.println(s);
Java 11 以降では _ を使って、より明示的に「この引数は使わない」と表せます。
// Java11以降
BiConsumer<String, Integer> printer = (s, _) -> System.out.println(s);
これにより、読み手も「この引数は無視されている」ことが一目でわかります。
Pythonにおける _
一方、Python では _ は予約語ではなく「普通の変数名」です。
ただし、慣習的に未使用変数として _ を使う のが一般的です。
1. for文での利用
for _ in range(3):
print("Hello")
range(3) が返す 0,1,2 は使わないため _ を置いています。
2. アンパックでの利用
pairs = [(1, "a"), (2, "b")]
for _, value in pairs:
print(value) # a, b
タプルの一部を無視する際にも _ を利用します。
3. 注意点
実際には _ に値が代入されています(特別扱いではない)。
対話モード(REPL)では _ が「直前の評価結果」を保持するため、注意が必要です。
他言語における _
Go
Go では _ は 文法レベルでの「捨て変数」 です。代入しても保持されません。
value, _ := someFunc() // エラー値を捨てる
慣習ではなく、仕様として「値を捨てる」仕組みになっています。
Rust
Rust も _ を未使用変数として利用できます。
for _ in 0..3 {
println!("Hello");
}
さらに _var のようにアンダースコアで始まる変数は「使わなくても警告が出ない」仕組みです。
Kotlin / Swift
Kotlin や Swift ではラムダ式で未使用引数を _ と書けます。
list.forEach { _ -> println("Hello") }
list.forEach { _ in print("Hello") }
Java 11 の仕様はこれらに近い形だと言えます。
Haskell / Scala / F#
関数型言語では _ が「ワイルドカード」として広く利用されます。
case xs of
[] -> "empty"
(_:_) -> "not empty"
JavaとPythonの違いの本質
Java
Java 9 以降 _ は変数名にできない
Java 11 で「ラムダ式の未使用パラメータ」を明示できるようになった
→ 仕様としてサポート
Python
_ は普通の変数だが、慣習として「未使用」を表す
→ 開発者の文化によるルール
要するに、Java は 「言語仕様で保証」 、Python は「慣習で表現」という違いがあります。
実務でのベストプラクティス
Java
_ はラムダ引数が1つ程度なら明示的に使ってOK
2つ以上だと ( _, _ ) -> ... のように可読性が落ちるため、ignored1, ignored2 とする方が親切
Python
for文やアンパックでは _ を積極的に使う
複雑な処理で _ が乱立するなら unused など明示的な名前にする
チーム開発
コード規約やリンター(JavaならCheckstyle、PythonならFlake8/Pylint)でルールを統一するとレビューがスムーズ
まとめ
Python は慣習で、Go は仕様で、Java はバージョンアップで――。
同じ「未使用変数の扱い」でもアプローチは言語ごとに違います。
Java 11 の _ もその流れの中で生まれたものであり、「明示的に意図を示す」ことを大切にするJavaらしい進化 と言えるでしょう。