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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2827293/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-11 01:29:55  来源:igfitidea点击:

Scala's '::' operator, how does it work?

listscalaoperator-keyword

提问by Felix

In Scala, I can make a caseclass, case class Foo(x:Int), and then put it in a list like so:

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

List(Foo(42))

Now, nothing strange here. The following is strange to me. The operator ::is a function on a list, right? With any function with one argument in Scala, I can call it with infix notation. An example is 1 + 2is a function (+)on the object Int. The class FooI just defined does not have the ::operator, so how is the following possible?

现在,这里没什么奇怪的了。以下对我来说很奇怪。运算符::是列表中的函数,对吗?对于 Scala 中带有一个参数的任何函数,我都可以用中缀表示法调用它。一个例子1 + 2是一个函数(+)的对象上IntFoo我刚刚定义的类没有::操作符,那么下面怎么可能呢?

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

In Scala 2.8 RC1, I get the following output from the interactive prompt:

在 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))

I can go on and use it, but what is the explanation?

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

采纳答案by retronym

From the Spec:

从规范:

6.12.3 InfixOperations An infix operator can be an arbitrary identifier. Infix operators have precedence and associativity defined as follows.

...

The associativity of an operator is determined by the operator's last character. Operators ending in a colon ‘:' are right-associative. All other operators are left- associative.

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

...

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

You can always see how these rules are applied in Scala by printing the program after it has been through the 'typer' phase of the compiler:

通过在编译器的“打字机”阶段之后打印程序,您始终可以看到这些规则是如何在 Scala 中应用的:

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

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

回答by folone

It ends with a :. And that is the sign, that this function is defined in the class to the right (in Listclass here).

它以:.结尾。这就是标志,这个函数是在右边的类中定义的(在List这里的类中)。

So, it's List(Foo(2)).::(Foo(40)), not Foo(40).::(List(Foo(2)))in your example.

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

回答by Thomas Jung

One aspect missing in the answers given is that to support ::in pattern matching expressions:

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

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]) 

so case ::(x,xs)would produce the same result. The expression case x :: xsworks because the default extractor ::is defined for the case class and it can be used infix.

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

回答by Surya Suravarapu

The class FooI just defined does not have the ::operator, so how is the following possible:

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

Foo我刚刚定义的类没有::操作符,所以以下怎么可能:

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

If the method name ends with a colon (:) the method is invoked on the right operand, which is the case here. If the method name doesn't end with colon, the method is invoked on the left operand. For example, a + b, +is invoked on a.

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

So, in your example, ::is a method on its right operand, which is a List.

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