An extractor can be any stable object, including instantiated classes with an unapply method:
A custom extractor is typically created in the companion object of the class.
A custom extractor is typically created in the companion object of the class. In this exercise, we use it as an assignment:
What's an extractor? In Scala it's a method in any object
called unapply
, and that method is used to disassemble the object given by returning a tuple wrapped in an option.
What's an extractor? In Scala it's a method in any object
called unapply
, and that method is used to disassemble the object given by returning a tuple wrapped in an option. Extractors can be used to assign values:
In Scala, patterns can be defined independently of case classes.
In Scala, patterns can be defined independently of case classes. To this end, a method named unapply
is defined 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 } object TwiceTest extends Application { val x = Twice(21) x match { case Twice(n) => Console.println(n) } // prints 21 }
There are two syntactic conventions at work here:
case Twice(n)
will cause an invocation of Twice.unapply
, which is used to match 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
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)
.The code in the preceding example would be expanded as follows:
object TwiceTest extends Application { val x = Twice.apply(21) Twice.unapply(x) match { case Some(n) => Console.println(n) } // prints 21 }
The return type of an unapply
should be chosen as follows:
Boolean
. For instance case even()
T
, return a Option[T]
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)
.
When you create a case class, it automatically can be used with pattern matching since it has an extractor:
As long as the method signatures aren't the same, you can have as many unapply methods as you want:
An extractor can also be used in pattern matching:
In this exercise we use unapply
for pattern matching employee objects:
Since we aren't really using u
and v
in the previous pattern matching, they can be replaced with _
:
The parameterless execute method has been deprecated and will be removed in a future version of ScalaTest. Please invoke execute with empty parens instead: execute().
The trap method is no longer needed for demos in the REPL, which now abreviates stack traces, and will be removed in a future version of ScalaTest