省略括号的Groovy函数调用

2j4z5cfb  于 2022-11-01  发布在  其他
关注(0)|答案(2)|浏览(230)

根据gradle文档/第13.5.2节,我们可以在方法调用中省略括号:
括号对于方法调用是可选的。
但是,当我们尝试应用java插件时,它似乎不起作用。如果脚本包含以下行:

apply [plugin: 'java']

我们将得到错误:

Maybe something should be set in parentheses or a comma is missing?
 @ line 1, column 8.
     apply [plugin: 'java']
            ^

但是如果我们把这个Map-literal放在一个括号里,它就可以正常工作了。

apply([plugin: 'java'])

所以当自变量是Map时,我们不能省略括号,对吗?

dhxwm5r4

dhxwm5r41#

正如规范所述,括号可以省略***当不存在歧义时***。我怀疑这种情况下的歧义是因为没有括号的语句看起来很像数组索引语法,解析器很难判断您是在调用名为'apply'的方法还是试图对名为'apply'的数组执行某些操作。
就我个人而言,这就是为什么我总是倾向于使用括号--如果解析器不能解出它,我相信另一个阅读代码的程序员也不会。

33qvvth1

33qvvth12#

虽然Groovy中数组或Map的常用语法确实使用括号(例如,对于空的,您通常分别写为[][:]),如果标识符后面跟有相同的括号符号,则会将其解释为索引运算符。然后,Groovy会尝试将apply解释为Gradle项目的属性,即使它并不存在。作为一种动态语言,允许我们动态地定义属性,因此并不总是有办法在编译时判断某个属性是否存在。虽然这是一个好的设计还是值得怀疑的,但Gradle的ExtraPropertiesExtension在Groovy中大量利用了这种动态特性,以方便使用。如果您喜欢更严格的类型,我建议您尝试KotlinDSL,这类问题要少得多(我不认为它已经完全消失了,因为我们仍然可以显式地将变量声明为dynamic type)。
另一方面,DSL的一个目的是简洁并去除无用的仪式。这是Groovy擅长的一件事,因为如果需要传递给方法或闭包的唯一参数只是一个数组或Map,则可以省略各种括号:apply plugin: 'java'。(对于DSL来说,任何比这更复杂的东西都是有问题的。)
这就是为什么我认为一直加括号(例如,apply([plugin: 'java']))到任何地方都不是构建脚本的正确方法,这些脚本的代码应该看起来是声明性的,并支持这一点,非常像DSL,至少如果您使用Groovy就不是这样,Groovy正是为此目的而设计的。永远不要使用语言特性,即使它可能有优势,是什么导致了像Douglas Crockford's JavaScript: The Good Parts这样的书,作者建议我们总是使用分号,这是互联网上争论最多的做法之一,eidogg.不同意的JavaScript Standard Style。我个人认为更重要的是了解你使用的语言,eidogg.,知道什么时候需要分号,一般来说,要产生最好质量的代码。分号的例子可能是公认的不是一个强有力的例子,除了简化仪式。但是仅仅因为一个语言特性可能被误用,这并不意味着我们应该禁止它的使用。菜刀并不坏,因为我们可以用它伤害别人。同样的道理也适用于Kotlin。这是最有判断力的特征。
虽然现在我们得到了
插件DSL,这是加载插件的首选方式
(即使插件放在buildSrc中,也只需要一些元数据定义),但由于以下原因,这个问题可能仍然相关:

  • 编程地应用插件,例如subprojects { apply plugin: 'java' }
  • 包括使用类似语法的自定义生成脚本:apply from: 'myscript.gradle'
  • 或者由于某种原因,您只能通过类名称引用插件。

因此,这个问题仍然有效。

相关问题