Scala方法调用中括号的规则是啥?

Posted

技术标签:

【中文标题】Scala方法调用中括号的规则是啥?【英文标题】:What is the rule for parenthesis in Scala method invocation?Scala方法调用中括号的规则是什么? 【发布时间】:2011-07-10 18:29:01 【问题描述】:

toList 不就是将某物转化为 List 的方法吗?

如果是,那为什么我不能用括号呢?我一定在这里遗漏了一些更基本的东西。

示例如下:

val l = Array(1,2,3).toList // works fine

val l = Array(1,2,3).toList() // gives the error below

方法 apply 的参数不足:(n: Int)Int in trait 线性序列优化。未指定值参数n。

【问题讨论】:

在这里找到了一个类似的问题,可能会有所帮助:Confused about Scala method calling conventions, specifically the sum function on Seq 【参考方案1】:

如果一个方法被定义为

def toList =  /* something */ 

那么它必须被称为

object.toList

没有额外的括号。我们说这个方法有零个参数列表

我们也可以定义一个参数列表,但什么都不放:

def toList() =  /* something */ 

现在,我们可以调用任何一个

object.toList()
object.toList

因为 Scala 允许在方法调用中省略括号。

就JVM而言,第一个定义(“零参数列表”)和第二个定义(“一个空参数列表”)没有区别。但 Scala 保持着一种区别。这是否是一个好主意值得商榷,但当你意识到我们也可以时,动机可能会更清楚

def toList()() =  /* something */ 

也就是所谓的两个空参数列表,然后调用任意一个

object.toList()()
object.toList()
object.toList

现在,如果我们要将其转换为函数,我们将其键入为

() => () => T   /* T is the return value of the something */

而第二个定义是

() => T

这在概念上明显不同,即使实际上你以相同的方式使用它(什么都不加,迟早会得到T)。

无论如何,toList 不需要任何参数,并且 Scala 标准是省略括号,除非方法更改对象本身(而不是仅仅返回某些内容),所以它是 def toList 之后没有任何括号。因此,您只能将其称为object.toList

【讨论】:

你的解释很棒。我很难想象 toList()() 的目的,但我现在会相信 scala... 你忘了提到额外的括号会产生错误,因为它被认为是结果 Listapply 方法。 @JeffLee - 不,(,) 是无效的语法。 ()() 是两个空参数列表(只有 Scala 知道;对于其他任何东西,它看起来就像一个没有参数的方法)。 @JeffLee - 你是说(a: Int, b: Int) 还是(a: Int)(b: Int)?这些对于 Scala 也不相同:一个有一个带有两个参数的参数列表,而另一个有两个带有一个参数的参数列表。 (但在字节码中,它们的实现方式相同;JVM 不知道多个参数列表。) @JeffLee - Scala 库广泛使用该功能来进行隐式,并使事物看起来像语言的内置方面。例如,list.foldLeft(0) (sum, x) => sum + x 使用两个参数列表定义(您将初始值和将另一个列表元素合并到结果中的函数放入其中)。【参考方案2】:

您的第二行实际上被解释为

val l = Array(1,2,3).toList.apply()

因为foo(x)foo.apply(x) 的“神奇”语法。

这就是编译器抱怨“没有足够的参数”的原因,因为列表上的 apply 方法需要一个参数。

因此你可以写例如:

scala> val i = Array(1, 2, 3).toList(1)
i: Int = 2

【讨论】:

也许这就是为什么如果方法没有参数,最好不要声明它。然后你可以像上面一样使用“链接”。 但同时很难判断 (1) 是方法的参数还是要应用于方法结果。 :-|【参考方案3】:

让我从 Scala 编码风格的角度来回答。

Scala style guide 说...

省略空括号,仅在所讨论的方法没有副作用(纯功能)时使用。换句话说,在调用 queue.size 时省略括号是可以接受的,但在调用 println() 时则不行。

虔诚地遵守此约定将显着提高代码的可读性,并使任何给定方法的最基本操作一目了然。忍住为了节省两个字符而省略括号的冲动!

【讨论】:

以上是关于Scala方法调用中括号的规则是啥?的主要内容,如果未能解决你的问题,请参考以下文章

Scala中调用函数或者方法为啥有时候需要括号,有时候不需要括号

2021年大数据常用语言Scala:基础语法学习 方法调用方式

在 VBA 函数调用中使用括号的规则是啥?

Scala学习——高级特性

scala初学

没有参数的 Scala 方法