Scala 的“::”运营商,它是如何工作的?

发布于 2024-09-01 09:50:35 字数 622 浏览 6 评论 0原文

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

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

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

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 + 2 is a function (+) on the object Int. The class Foo I just defined does not have the :: operator, so how is the following possible?

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

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

风吹短裙飘 2024-09-08 09:50:35

从规格来看:

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)
};

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.

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 -Xprint:typer -e "1 :: Nil"

val r: List[Int] = {
  <synthetic> val x$1: Int = 1;
  immutable.this.Nil.::[Int](x$1)
};
GRAY°灰色天空 2024-09-08 09:50:35

它以 : 结尾。这就是标志,该函数是在右侧的类中定义的(在此处的 List 类中)。

因此,它是 List(Foo(2)).::(Foo(40)),而不是 Foo(40).::(List(Foo(2))) 在你的例子中。

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

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

深海蓝天 2024-09-08 09:50:35

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

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 有效,因为默认提取器 :: 是为 case 类定义的,并且可以中缀使用。

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 :: xs works because the default extractor :: is defined for the case class and it can be used infix.

喵星人汪星人 2024-09-08 09:50:35

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

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

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

因此,在您的示例中, :: 是其右侧操作数(即 List)上的方法。

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

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.

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文