Scala Unapply Sequences
An unapplySeq method is an extractor that returns a variable-length list of parts. It lets one pattern match a value with any number of pieces.
A star binds the leftover words
Words splits a sentence into a sequence of words. The star binds every word after the first.
object Words:
def unapplySeq(s: String): Option[Seq[String]] =
Some(s.split(" ").toSeq)
@main def main(): Unit =
val result = "red green blue" match
case Words(first, rest*) => first + ":" + rest.length
case _ => "no"
println(result)A fixed pattern matches exactly two words
With two names and no star, the pattern needs exactly two words. This sentence has exactly two.
object Words:
def unapplySeq(s: String): Option[Seq[String]] =
Some(s.split(" ").toSeq)
@main def main(): Unit =
val result = "sun moon" match
case Words(x, y) => x + "-" + y
case _ => "no"
println(result)A star can bind nothing
One word leaves no leftovers for the star. The star then binds an empty sequence.
object Words:
def unapplySeq(s: String): Option[Seq[String]] =
Some(s.split(" ").toSeq)
@main def main(): Unit =
val result = "single" match
case Words(first, rest*) => first + ":" + rest.length
case _ => "no"
println(result)Example
object Words:
def unapplySeq(s: String): Option[Seq[String]] =
Some(s.split(" ").toSeq)
@main def main(): Unit =
val result = "buy milk eggs bread" match
case Words(verb, items*) => verb + " " + items.length + " items"
case _ => "no"
println(result)Key points
- unapplySeq: an extractor method that returns an Option of a sequence of parts.
- Use a star pattern such as rest* to bind the leftover parts as a sequence.
- A fixed pattern such as Words(first, second) matches only two parts.
- A pattern with a star at the end matches one or more parts.
- The bound star name holds a sequence, so its length tells how many leftovers matched.
In this example, Words splits the sentence into four words. The verb binds to buy, and the star binds the three remaining words. The length of the star binding gives the item count.
Note
unapplySeq and unapply differ only in the result type, so a value with a fixed shape uses unapply.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Scastie
Exercise
For "a b c d" matched with case Words(first, rest*) => rest.length, what is rest.length?