Scala Extractors
An extractor is an object with an unapply method that pulls a value apart in a match. It lets a match test a value and bind a part of it in one step.
An extractor splits an even number
Even unapply returns Some of the half for an even number. The match binds that half to a name.
object Even:
def unapply(n: Int): Option[Int] =
if n % 2 == 0 then Some(n / 2) else None
@main def main(): Unit =
val result = 10 match
case Even(half) => half
case _ => -1
println(result)None sends the match to the next case
For an odd number, unapply returns None. The catch-all case then runs.
object Even:
def unapply(n: Int): Option[Int] =
if n % 2 == 0 then Some(n / 2) else None
@main def main(): Unit =
val result = 7 match
case Even(half) => half
case _ => 0
println(result)An extractor can split a string
A string extractor can split a name into two parts. The match binds both parts at once.
object Name:
def unapply(s: String): Option[(String, String)] =
val parts = s.split(" ")
if parts.length == 2 then Some((parts(0), parts(1))) else None
@main def main(): Unit =
val result = "Ada Lovelace" match
case Name(first, last) => last + ", " + first
case _ => "no"
println(result)Example
object Even:
def unapply(n: Int): Option[Int] =
if n % 2 == 0 then Some(n / 2) else None
def halve(n: Int): Int = n match
case Even(half) => half
case _ => -1
@main def main(): Unit =
println(List(10, 7, 12).map(halve))Key points
- Extractor: an object whose unapply method turns a value into an Option of parts.
- Use a pattern such as Even(half) to test a number and bind its half in one step.
- A Some result means the pattern matches and its contents become the bound names.
- A None result means the pattern does not match and the next case is tried.
- Use an extractor for a test that a plain literal pattern cannot express.
In this example, halve matches each number against Even. Even numbers give their half, and the odd number falls through to -1. The mapped list shows all three results in order.
Note
unapply is a plain method, so it can hold any test that returns an Option.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Scastie
Exercise
What does 8 match with case Even(half) => half and case _ => 0 give?