Introduction to Scala Part3: Option & Pattern Matching
Bubu
3,319 views
Extractor Objects
In Scala, patterns can be defined using a method named unapply to yield a so-called extractor. For instance, the following code defines an extractor object Twice:
object Twice {
def apply(x: Int): Int = x * 2
def unapply(z: Int): Option[Int] = if (z%2 == 0) Some(z/2) else None
}
val x = Twice(21)
x match { case Twice(n) => Console.println(n) } // prints 21
There are two syntactic conventions at work here:
- The pattern case Twice(n) will cause an invocation of Twice.unapply, which is used to match any even number;
- The return value of the unapply signals whether the argument has matched or not, and any sub-values that can be used for further matching. Here, the sub-value is z/2
The apply method is not necessary for pattern matching. It is only used to mimick a constructor.val x = Twice(21) expands to val x = Twice.apply(21).
Extractor: unapply and unapplySeq
The return type of an unapply should be chosen as follows:
- If it is just a test, return a Boolean. For instance case even()
- If it returns a single sub-value of type T, return an Option[T]
- If you want to return several sub-values T1,...,Tn, group them in an optional tuple Option[(T1,...,Tn)].
Sometimes, the number of sub-values is fixed and we would like to return a sequence. For this reason, you can also define patterns through unapplySeq. The last sub-value type Tn has to be Seq[S]. This mechanism is used for instance in pattern case List(x1, ..., xn).
Pattern in value definition
class Person(firstname: String, lastName: String)
object Person {
def apply(firstname: String, lastname: String): Person = …
def unapply(person: Person) : Option[(String, String)] = ...
}
val Person(firstname, lastname) = Person("A", "B")
// firstname : String = "A"
// lastname: String = "B"
val Person(_, toto) = Person("A", "B")
// toto : String = "B"
def kingOfTheNorth(): Person = Person("John", "Snow")
kingOfTheNorth // Person("John", "Snow")
apply Person
unapply Person
Create your playground on Tech.io
This playground was created on Tech.io, our hands-on, knowledge-sharing platform for developers.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package fp101.tp03.patternmatching
object ExercicePersonMatching {
class Person(val firstname: String, val lastname: String)
object Person {
def apply(firstname: String, lastname: String) = ???
def unapply(person: Person): Option[(String, String)] = ???
}
/*
*
* test code:
*
* val person = Person("John", "Snow")
*
* val Person(firstName, lastName) = person
*
* person match {
*
* case Person(a,b) => println(a + " " + b)
*
* }
*
*/
}