🧩

Scala 2 で学ぶ Unit 型――“値がある void” の正体と便利ワザ入門

に公開

1. Unit ってそもそも何?🧩

言語 "戻り値なし" キーワード その実態
Java void 型を持たない (値を返せない)
Scala Unit 値を一つだけ持つ型 () という定数
  • Unit は「たった 1 つの値(())だけを取れる型」
    = 戻り値が“意味的に不要”でも 型システム上は値を返している
  • null と異なり NPE の心配ゼロ
  • void と異なり 関数合成が途切れない(後述)

2. REPL で動かしてみる 🔧

% scala
Welcome to Scala 2.13.14 (OpenJDK 64-Bit Server VM, Java 24.0.1).
Type in expressions for evaluation. Or try :help.

scala> val u = ()
val u: Unit = ()

scala> u == ()
         ^
       warning: comparing values of types Unit and Unit using `==` will always yield true
val res0: Boolean = true

scala> u.getClass // 実体はある!
val res1: Class[Unit] = void

関数の戻り値に現れる

scala> def log(msg: String): Unit = println(s"[LOG] $msg")
def log(msg: String): Unit

scala> val r = log("hello")
[LOG] hello
val r: Unit = () // 呼び出し結果は ()

3. “値がある” 利点を体感:for 内包表記で合成🏗️

scala> val xs = Vector(1, 2, 3)
val xs: scala.collection.immutable.Vector[Int] = Vector(1, 2, 3)

scala> val res = for {
     | x <- xs
     | _ = log(s"processing $x") // Unit を返す式
     | } yield x * 10 // 合成できる!
[LOG] processing 1
[LOG] processing 2
[LOG] processing 3
val res: scala.collection.immutable.Vector[Int] = Vector(10, 20, 30)
  • for 内の各行は すべて式 = 値
  • log が Unit を返すおかげで位置を保てる
    (Java の void なら文になり脱線)

4. “副作用の明示” として使う例 ✍️

scala> def mutate(xs: collection.mutable.Buffer[Int]): Unit =
     | xs += 99 // 破壊的更新だけが目的
def mutate(xs: scala.collection.mutable.Buffer[Int]): Unit

scala> val buf = collection.mutable.Buffer(1, 2)
val buf: scala.collection.mutable.Buffer[Int] = ArrayBuffer(1, 2)

scala> val v: Unit = mutate(buf)
val v: Unit = () // 型を見れば「副作用だけ」と分かる

scala> buf
val res2: scala.collection.mutable.Buffer[Int] = ArrayBuffer(1, 2, 99)

5. よくある疑問 Q&A

Q A
Unit と () との違い? Unit は型名、() はその唯一の値(インスタンス)。Java で言えば boolean と true みたいな関係。
戻り値を書かなかったら? Scala 2 では最後の式の型が推論される。副作用しかない関数は暗黙に Unit。明示したほうが意図が伝わる。
null にできる? できるが非推奨。Unit は値が決まっているので null を使う意味がない。

6. まとめ 🌱

  • Unit は “値を返さない” のではなく “唯一の値 () を返す” 型
  • そのおかげで 式として合成 でき、関数型らしい書き方が崩れない
  • “副作用だけ” の関数を 型で宣言 できるのでコードの意図が明瞭

REPL で (): Unit を見かけたら「ここは副作用の関門だな」と考えるクセを付けましょう。Scala の型システムがあなたの設計を 1 行ごとに守ってくれます!

細かい用語補足

用語 ひらくと Scala 2 初学者向けイメージ
NPE Null Pointer Exception null を参照したままメソッドを呼んだりフィールドにアクセスしようとしたときに発生する典型的なランタイム例外。Java / Scala どちらでも起きます。
副作用 (side effect) 「結果(戻り値)以外にプログラムの状態を変えること」 たとえば 標準出力に文字を出す、可変コレクションを書き換える、ファイルを書き込む、DB を更新する など。「返り値を返さない」こと自体ではなく「関数外の世界が変わる」ことが本質です。

Discussion