Scala的'::'运算符,它是如何工作的?

时间:2010-05-13 13:52:52

标签: list scala operator-keyword

在Scala中,我可以创建一个caseclass case class Foo(x:Int),然后把它放在一个这样的列表中:

List(Foo(42))

现在,这里没什么奇怪的。以下对我来说很奇怪。运算符::是列表中的函数,对吧?对于Scala中有一个参数的任何函数,我可以用中缀表示法调用它。 一个例子是1 + 2是对象(+)上的函数Int。我刚刚定义的类Foo没有::运算符,那么以下内容如何可能?

Foo(40) :: List(Foo(2))

在Scala 2.8 RC1中,我从交互式提示中获得以下输出:

scala> case class Foo(x:Int)
defined class Foo

scala> Foo(40) :: List(Foo(2))
res2: List[Foo] = List(Foo(40), Foo(2))

我可以继续使用它,但解释是什么?

4 个答案:

答案 0 :(得分:48)

来自规范:

  

6.12.3 InfixOperations中缀运算符可以是任意的   标识符。中缀运营商有   优先级和关联性定义   如下。

     

...

     

运营商的关联性是   由运营商的最后一个决定   字符。以冒号结尾的运算符   ':'是正确联想的。所有其他   运算符是左联的。

通过在编译器的'typer'阶段完成后打印程序,您始终可以看到如何在Scala中应用这些规则:

scala -Xprint:typer -e "1 :: Nil"

val r: List[Int] = {
  <synthetic> val x$1: Int = 1;
  immutable.this.Nil.::[Int](x$1)
};

答案 1 :(得分:21)

:结尾。这就是符号,这个函数是在右边的类中定义的(这里是List类)。

因此,在您的示例中,它是List(Foo(2)).::(Foo(40)),而不是Foo(40).::(List(Foo(2)))

答案 2 :(得分:17)

给出的答案中缺少的一个方面是在模式匹配表达式中支持::

List(1,2) match {
  case x :: xs => println(x + " " + xs)
  case _ => println("")
}

A class :: is defined

final case class ::[B](private var hd: B, private[scala] var tl: List[B]) 

所以case ::(x,xs)会产生相同的结果。表达式case x :: xs有效,因为为案例类定义了默认提取器::,并且可以使用中缀。

答案 3 :(得分:15)

  

我刚才定义的班级Foo没有   有::运算符,那么它是怎么回事   以下可能:

     

Foo(40) :: List(Foo(2))

如果方法名称以冒号(:)结尾,则在右操作数上调用该方法,这是这里的情况。如果方法名称不以冒号结尾,则在左操作数上调用该方法。例如,a + b上会调用+a

因此,在您的示例中,::是右侧操作数上的一个方法,即List