斯卡拉的“::”运算符,它是如何工作的?

在Scala中,我可以创buildcaseclass, case class Foo(x:Int) ,然后将它放在如下所示的列表中:

 List(Foo(42)) 

现在,这里没什么奇怪的。 以下对我来说很陌生。 operator ::是一个列表上的函数,对吗? 在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)) 

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

从规格:

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

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

您可以随时通过在编译器的“typer”阶段之后打印程序来了解Scala如何应用这些规则:

 scala -Xprint:typer -e "1 :: Nil" val r: List[Int] = { <synthetic> val x$1: Int = 1; immutable.this.Nil.::[Int](x$1) }; 

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

所以,在你的例子中,是List(Foo(2)).::(Foo(40)) ,而不是Foo(40).::(List(Foo(2)))

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

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

类::定义 :

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

所以case ::(x,xs)会产生相同的结果。 expression式case x :: xs工作原理是因为默认的提取器::是为case类定义的,它可以用于中缀。

我刚刚定义的类Foo没有::运算符,那么以下可能如何:

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

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

所以,在你的例子中, ::是右边操作数的一个方法,它是一个List