🔎

Scalaパターンマッチ入門:コンストラクタ・シーケンス・タプルを体感する

に公開

Scala の魅力のひとつに 強力なパターンマッチ があります。
本記事では REPL を使いながら、以下の3種類のパターンを体感していきます。

  • コンストラクターパターン
  • シーケンスパターン
  • タプルパターン

「写経して動かすと直感的に理解できる」形式でまとめてみました。

1. 準備:Scala REPL を開く

ターミナルで以下を実行します。

% scala

これで対話環境が起動します。あとはコピペで大丈夫です。

2. コンストラクターパターン

まずは「式がオブジェクトのコンストラクタ形と一致するか」を判定するパターンです。
例えば以下の簡単な式クラスを定義します。

scala> sealed trait Expr
trait Expr

scala> case class BinOp(op: String, left: Expr, right: Expr) extends Expr
class BinOp

scala> case class Number(value: Int) extends Expr
class Number

scala> case object VarX extends Expr
object VarX

BinOp は二項演算子、Number は数値、VarX は変数を表すものとします。

ここでパターンマッチ!

scala> val expr: Expr = BinOp("+", Number(1), Number(0))
val expr: Expr = BinOp(+,Number(1),Number(0))

scala> expr match {
     |   case BinOp("+", _, Number(0)) => println("加算の右がゼロ -> 簡略化できる!")
     |   case BinOp("*", _, Number(1)) => println("掛け算の右が1 -> 簡略化できる!")
     |   case _ => println("その他")
     | }
加算の右がゼロ -> 簡略化できる!

「構造そのもの」にマッチする感覚が分かると思います。

3. シーケンスパターン

リストや配列に対して、長さや要素に基づいてマッチできます。

scala> def describeList(xs: List[Int]) = xs match {
     |   case List(0, _, _) => "先頭が0で長さ3"
     |   case List(1, _*) => "先頭が1で残りはなんでもOK"
     |   case Nil => "空リスト"
     |   case _ => "その他"
     | }
def describeList(xs: List[Int]): String

動かしてみましょう。

scala> describeList(List(0, 2, 3))
val res1: String = 先頭が0で長さ3

scala> describeList(List(2, 5, 6, 7))
val res2: String = その他

scala> describeList(Nil)
val res3: String = 空リスト

_* が「残り全部」というシンタックスで、かなり直感的に書けます。

4. タプルパターン

複数要素をまとめるタプル (a, b, c) に対してもパターンマッチできます。

scala> def tupleDemo(expr: Any) = expr match {
     |   case (a, b, c) => s"3要素タプル: $a, $b, $c"
     |   case _ => "その他"
     | }
def tupleDemo(expr: Any): String

動作確認:

scala> tupleDemo(("hello", 42, true))
val res0: String = 3要素タプル: hello, 42, true

変数を一気に分解できるので、関数の戻り値処理にも便利です。

まとめ

  • コンストラクターパターン: オブジェクトの構造に直接マッチできる(代数的データ型と相性抜群)
  • シーケンスパターン: List/Array に自然な形でマッチ(_* で残り全部キャッチ)
  • タプルパターン: 複数要素を一気に分解できる

Scala のパターンマッチは 「if文やswitchの代わり」以上の威力 を持っています。
REPL で試すと理解が一気に深まりますので、ぜひ写経して「おぉ〜」を体験してみてください。

Discussion