kmizuの日記

プログラミングや形式言語に関係のあることを書いたり書かなかったり。

お役立ち中置パターン in Scala

Scalaには中置パターン(infix pattern)と呼ばれる機能があります。これは単純にいうと、

case class ~[A, B](a: A, b: B)

のようにして定義したケースクラスに対して*1

scala> val ab = new ~(1, "FOO")
ab: ~[Int,String] = ~(1,FOO)

scala> val a ~ b = ab
a: Int = 1
b: String = FOO

このようにパターン名を中置(infix)にして書くことができる機能です。この機能、一見使い道が少なそうですが、実は皆さん、日頃からよく使われています。

まず、

list match {
  case x::y::xs =>
  ...
}

のように、リストを::を使ったパターンマッチで分解することはよくあると思いますが、これは、::という中置パターンがあればこそできる書き方です。これができないと、

list match {
  case ::(x, ::(y, xs)) => 
}

のように、いちいちネストした形式でパターンを書く必要があり、これは書きやすくも読みやすくもありません。

また、Scalaのパーザコンビネータを使ったとき、

"(" ~ expression ~ ")" ^^ { case _ ~ e ~ _ =>
  ...
}

のようにして、マッチした式の値のうち一部だけを取り出しますが、これも~を中置パターンとして使えているからこそです。これがないと、

"(" ~ expression ~ ")" ^^ { case ~(~(_, e), _) =>
  ...
}

のようにネストした形でパターンを記述する必要があり、とてもuglyです。~でつながれる要素数がさらに増えるともはや書き下すことが難しくすらなります。

というわけで、中置パターンは便利です、という話でした。

*1:実際には、unapplyが定義されていればいいわけですが、説明の簡略化のためその辺はばっさり略