开发者

Case classes, pattern matching and curried constructors in Scala

They don't seem to mix that well:

abstract class A
case class B (var a: Int)(var b: String) extends A
case class C extends A

The following will not work:

B(1)("1") match {
  case B(a)(b) => print("B")
  case C() => print("C")
}

The problem is that pattern matching and curried argumen开发者_JAVA技巧ts do not seem to work. Is there a work-around for this?


If you look at the signature of the unapply function created for the class B, you will see that it is: unapply(x$0: Q): Option[Int]. Thus, the unapply function works with the first range of parameter of the case classes.

It is confirmed by the scala specification (§5.3.2):

The formal parameters in the first parameter section of a case class are called elements; they are treated specially. First, the value of such a parameter can be extracted as a field of a constructor pattern.

It claims clearly tha only the first parameter section is available through the extractor.

Several workarounds:

  • uncurry your parameters
  • use a pattern matching with guard if you want to test the 2 values: case x@B(3) if x.b == "bazinga" => ...
  • use a normal class and define your own companion object with your own apply / unapply


What's wrong with this?

def m(a: A) = a match {
  case b: B => print("B")
  case c: C => print("C")
}

I'm only asking because you didn't ask for more functionality than this.

EDIT

This could help:

object Dog {
   def apply(name: String)(size: Int) = new Dog(name)(size)
   def unapply(dog: Dog) = Some(dog.name, dog.size)
}
class Dog(val name: String)(var size: Int)

Now you can create dogs either like this:

new Dog("Snoopy")(10) 

or like this:

Dog("Snoopy")(10)

But when you pattern match on dogs the constructor pattern is not curried.

Dog("Snoopy")(10) match {
   case Dog(a, b) => // do sth with a or b
}


You could use a normal case class and just define a factory method with more than one parameter list.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜