简体   繁体   English

Scala中的案例类,模式匹配和curried构造函数

[英]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 arguments do not seem to work. 问题是模式匹配和curried参数似乎不起作用。 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] . 如果你看一下为B类创建的unapply函数的签名,你会看到它是: unapply(x$0: Q): Option[Int] Thus, the unapply function works with the first range of parameter of the case classes. 因此,unapply函数与case类的第一个参数范围一起使用。

It is confirmed by the scala specification (§5.3.2): scala规范(§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 xb == "bazinga" => ... 如果要测试2个值,请使用与guard匹配的模式: case x@B(3) if xb == "bazinga" => ...
  • use a normal class and define your own companion object with your own apply / unapply 使用普通类并使用您自己的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
}

您可以使用普通的case类,只需定义一个带有多个参数列表的工厂方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM