Reputation: 23114
Code:
case class Division(val number: Int) {
// def unapply(divider: Int): Option[(Int, Int)] = if (number % divider == 0) Some(number/divider, 0) else None
// def unapply(divider: Double): Boolean = number % divider.toInt == 0
def unapplySeq(x: Float): Option[Seq[Int]] = {
val seq = (3 to 10).map(i => i * x.toInt)
println(seq)
Some(seq)
}
}
val divisionOf15 = Division(15)
// val y = 5 match {
// case divisionOf15(z, w) => println(s"$z, $w")
// case _ => println(s"Not divisible")
// }
// val z = 5.0 match {
// case divisionOf15() => println("Divisible")
// case _ => println("Not divisible")
// }
val u = 5.0F match {
case divisionOf15(f1, f2, _*) => println(s"$f1, $f2")
}
If I uncomment these lines:
// def unapply(divider: Int): Option[(Int, Int)] = if (number % divider == 0) Some(number/divider, 0) else None
// def unapply(divider: Double): Boolean = number % divider.toInt == 0
An error crops up during compilation:
Star pattern must correspond with varargs or unapplySeq
case divisionOf15(f1, f2, _*) => println(s"$f1, $f2")
^
If I uncomment this line:
// def unapply(divider: Int): Option[(Int, Int)] = if (number % divider == 0) Some(number/divider, 0) else None
I get two errors:
scrutinee is incompatible with pattern type;
found : Int
required: Float
case divisionOf15(f1, f2, _*) => println(s"$f1, $f2")
^
Star pattern must correspond with varargs or unapplySeq
case divisionOf15(f1, f2, _*) => println(s"$f1, $f2")
^
Am I doing something wrong or is this a bug? These extractors seem innocent and shouldn't conflict with each other.
Upvotes: 4
Views: 133
Reputation: 67290
The language specification does not say anything about the concurrent presence of unapply
and unapplySeq
. It hints at their mutual exclusiveness, though:
an object which has a member method named
unapply
orunapplySeq
...
if the extractor object x does not have an
unapply
method, but it does define anunapplySeq
method
This blog also states:
Note: if both unapply and unapplySeq are defined only unapply is used.
So either define different extractors (it doesn't seem obvious to me to overload the definitions in your case!), or go with unapply
:
case class Division(val number: Int) {
def unapply(divider: Int): Option[(Int, Int)] =
if (number % divider == 0) Some(number/divider, 0) else None
def unapply(divider: Double): Boolean = number % divider.toInt == 0
def unapply(x: Float): Option[Seq[Int]] = {
val seq = (3 to 10).map(i => i * x.toInt)
println(seq)
Some(seq)
}
}
val u = 5.0F match {
case divisionOf15(Seq(f1, f2, _*)) => println(s"$f1, $f2")
}
Upvotes: 5