Scala中缀运算符的匹配分解

10

我正在尝试理解 Scala 中 List 的实现。特别是,我正在努力理解如何使用中缀运算符编写匹配表达式,例如:

a match {
  case Nil => "An empty list"
  case x :: Nil => "A list without a tail"
  case x :: xs => "A list with a tail"
}

匹配表达式为什么可以写成x :: xs而不是List(x, xs)

3个回答

13

Jay Conrad的答案几乎是正确的。重要的是,在某个地方有一个名为::的对象,它实现了unapply方法,返回类型为Option[(A, List[A])]。因此:

object :: {
  def unapply[A](ls: List[A]): Option[(A, A)] = {
    if (ls.empty) None
    else Some((ls.head, ls.tail))
  }
}

// case objects get unapply for free
case object Nil extends List[Nothing]

对于::List而言,这个对象的出现是因为::是一个扩展了List特质的case class。然而,正如上面的例子所示,它并不一定非得是一个case class。


7
我认为 :: 实际上是一个类(它是 List 的子类),所以说 x :: xs 大多等同于 List(x, xs)
你也可以使用其他具有操作符名称的 case 类,例如:
case class %%%(x: Int, y: Int)

a match {
  case x %%% y => x + y
}

4
“匹配表达式如何允许使用 x :: xs 而不是 List(x, xs)?”
回答这个问题:
当作为“模式”看待时,中缀操作符(如 p op q)等同于 op(p, q),也就是说,中缀操作符 op 被视为构造函数模式。
(摘自《Scala编程》第一版,第331页)
另请参见 scala case classes questions

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接