12

我是 Scala 的初学者,我看到了一些调用方法的不同语法。有些很好,因为忽略无参数方法的括号,或忽略点,如

1 to 10

但有些真的让我很困惑。例如:

breakable { ... }

这只是一个方法调用对吗?我也可以对多个参数或不是无参数函数的参数执行此操作吗?

谢谢

4

2 回答 2

26

调用方法有两种标准方式:

obj.method(params)   // dot notation
obj method (params)  // operator notation

以上可以通过以下方式进行修改:

  1. 如果params是单个参数,则可以替换(){}.
  2. 如果params是单个参数并且您正在使用运算符表示法,则可以删除括号。
  3. 如果method不带参数,则可以丢弃(params)(即丢弃空的())。
  4. 如果method以 结尾:,那么它实际上绑定到运算符符号的右侧。即,(params) method_: obj等价于obj.method_:(params)
  5. 无论哪种方式,只要可以区分标识符,空格都是可选的。因此,人们可以在点符号中添加空格,例如obj . method ( params )在下.method(params)一行添加空格(就像调用链经常发生的情况一样),以及从运算符符号中删除空格,如a+b.

还有一些元组推理的东西,但我尽量避免它,所以我不确定确切的规则。

但是,这些都不能解释您感到困惑的示例。然而,在我解释它之前,我想展示一些也可以用来调用方法的语法糖:

obj(params) // equivalent to obj.apply(params)
obj.x = y   // equivalent to obj.x_=(y), if obj.x also exists
obj(x) = y  // equivalent to obj.update(x, y)
obj op= y   // equivalent to obj = obj op y, if op is symbolic
~obj        // equivalent to obj.unary_~; also for !, + and -, but no other symbol

好的,现在到你给出的例子。可以导入稳定值的成员。Java 可以通过静态导入为静态方法做到这一点,但 Scala 有一个更通用的机制:从包、对象或公共实例导入也不例外:它同时带来类型成员和值成员。方法属于后一类。

所以,想象你有val a = 2,你有import a._。这会将所有Int方法纳入范围,因此您可以直接调用它们。您不能这样做+(2),因为这将被解释为对 的调用unary_+,但您可以调用*(4),例如:

scala> val a = 2
a: Int = 2

scala> import a._
import a._

scala> *(4)
res16: Int = 8

现在,这是规则。你可以打电话

method(params)

如果:

  1. method已导入范围。
  2. 你保留括号(即使只有一个参数)

请注意,还有一个优先级问题。如果您编写obj method(params),Scala 将假定method属于obj,即使它已导入范围。

于 2012-08-10T15:31:27.730 回答
15

如果我们对此进行脱糖,我们将拥有:

breakable({ ... }) 

这匹配签名

breakable: (op: ⇒ Unit): Unit 

并使用如此命名的名称调用参数(您可能会认为这是将代码块作为参数传递

更多的 scala 允许你这样写:

scala> def foo (op1: => Unit)(op2: => Unit) = {op1;op2;}
foo: (op1: => Unit)(op2: => Unit)Unit

scala> foo { println(1) } { println(2) }
1
2

以上是柯里化函数的例子

于 2012-08-10T09:57:38.427 回答