E127: Not An Extractor
This error occurs when attempting to use a type as an extractor in a pattern match, but the type lacks an appropriate unapply or unapplySeq method.
In Scala, pattern matching with extractor syntax (like case Foo(x)) requires the type to have an unapply or unapplySeq method. Case classes automatically get these methods, but regular classes do not.
An unapply method should be in an object, take a single explicit term parameter, and:
- If it is just a test, return a
Boolean. For examplecase even() - If it returns a single sub-value of type T, return an
Option[T] - If it returns several sub-values T1,...,Tn, group them in an optional tuple
Option[(T1,...,Tn)]
Additionally, unapply or unapplySeq methods cannot take type parameters after their explicit term parameter.
Sometimes, the number of sub-values isn't fixed and we would like to return a sequence. For this reason, you can also define patterns through unapplySeq which returns Option[Seq[T]]. This mechanism is used for instance in pattern case List(x1, ..., xn).
Example
class Box(val x: Int)
def example(a: Any) = a match
case Box(x) => ()
Error
-- [E127] Pattern Match Error: example.scala:4:7 -------------------------------
4 | case Box(x) => ()
| ^^^
|Box cannot be used as an extractor in a pattern because it lacks an unapply or unapplySeq method with the appropriate signature
|-----------------------------------------------------------------------------
| Explanation (enabled by `-explain`)
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| An unapply method should be in an object, take a single explicit term parameter, and:
| - If it is just a test, return a Boolean. For example case even()
| - If it returns a single sub-value of type T, return an Option[T]
| - If it returns several sub-values T1,...,Tn, group them in an optional tuple Option[(T1,...,Tn)]
|
| Additionaly, unapply or unapplySeq methods cannot take type parameters after their explicit term parameter.
|
| Sometimes, the number of sub-values isn't fixed and we would like to return a sequence.
| For this reason, you can also define patterns through unapplySeq which returns Option[Seq[T]].
| This mechanism is used for instance in pattern case List(x1, ..., xn)
-----------------------------------------------------------------------------
Solution
// Use a case class which automatically provides an unapply method
case class Box(x: Int)
def example(a: Any) = a match
case Box(x) => x
case _ => 0
// Alternative: Define an explicit companion object with an unapply method
class Box(val x: Int)
object Box:
def unapply(box: Box): Option[Int] = Some(box.x)
def example(a: Any) = a match
case Box(x) => x
case _ => 0