在scala中匹配case类:〜(a,b)匹配{case a~b => ...}

时间:2010-07-14 12:41:02

标签: scala pattern-matching case-class

我有一个案例类

case class ~[a,b](_1:a, _2:b)

当我想做pattetn匹配时

new ~("a", 25) match{
  case "a" ~ 25 =>
}

我可以这样使用它,因为"a" ~ 25~("a", 25)是等价的。但是,如果我想要new ~("a", new ~("b", 25))匹配{case "a" ~ "b" ~ 25 => }麻烦开始。我知道这些陈述并不等同。那么,new ~("a", new ~("b", 25))如何呈现?按什么规则?

1 个答案:

答案 0 :(得分:10)

这有效:

new ~("a", new ~("b", 25)) match {
  case "a" ~ ("b" ~ 25) =>
}

因此,您必须将括号与初始子句中的括号相同。否则,波浪号是左关联的,因此模式的类型将不同,并且不会编译。

case "a" ~ "b" ~ 25

相同
case ("a" ~ "b") ~ 25

在你的情况下会出错。

<强>附录

通过将冒号作为类/方法名称中的最后一个字符,可以获得正确的关联性。以下编译和匹配没有括号(您可以删除new,因为编译器不会再被$tilde$colon混淆):

case class ~:[a,b](_1:a, _2:b)

~:("a", ~:("b", 25)) match {
  case "a" ~: "b" ~: 25 =>
}

<强>响应

1)如果没有new关键字,case class ~会被unary_~遮蔽,这会给出参数的按位否定。类似~ 2的表达式在内部评估为unary_~(2)~ ("a", 1)的情况也是如此 - 但除非您在该元组上定义unary_~,否则会出错。使用new关键字,您建议编译器显式查找具有该名称的类,因此不会混淆。 (从技术上讲,你可以使用$tilde("a", 1)作为case class ~的内部名称来解决这个问题,但由于这是一个编译器细节,你可能不应该依赖它。)

2&amp; 3)Scala Language Specification中引用了右关联性。 “中缀操作”部分

  

操作员的关联性由操作员的最后一个字符决定。以冒号':'结尾的运算符是右关联的。所有其他运算符都是左关联的。

顺便说一句,右关联性是允许使用Nil创建列表的技巧。 (Nil为空List,并定义了右关联连接运算符::。)

val l: List[Int] = 1 :: 2 :: 3 :: Nil

评估如下

val l: List[Int] = (1 :: (2 :: (3 :: Nil)))

或更确切地说,自3 :: NilNil.::(3)以来,

val l: List[Int] = ( ( Nil.::(3) ).::(2) ).::(1)