在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))
我可以继续使用它,但解释是什么?
答案 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("")
}
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
。