为什么Scala在调用一个arg函数时特别对待元组?

Scala将多个函数调用参数合并为一个元组 – 可以禁用吗? 讨论Scala创build一个绑定到一个arg函数的元组。 这导致

scala> println(1, 2) (1,2) 

答案是,编译器允许一个arg函数被调用而没有parens,所以在逻辑上这是一个调用println的元组。

但是println不能用一个元组参数调用

 scala> val t = (1, 2) t: (Int, Int) = (1,2) scala> println t <console>:6: error: value t is not a member of Unit println t ^ 

所以别的事情正在发生。 为什么元组在这里?

与此解释相反,Scala parsing println(1,2) (或者Console println (1,2)就像parsing任何双参数方法调用一样)。 稍后,编译器通过将元组中的方法参数包装成与实际方法types签名相匹配来转换调用。

如果编译器没有这样做, Console println (1,2)等完全有效的expression式将无法编译,因为println不带多个参数。 此行为还有其他有效的用例 。

从编译器的angular度考虑一个像foo bar (1,2)这样的expression式,牢记Scala有特殊的语法允许你删除它. 和方法调用的parens。 这可以是调用带参数12的双参数bar方法,也可以是使用单个元组值参数调用单参数bar方法。 parsing器不知道任何关于bar方法的知识,所以它只是parsing为一个双参数的方法调用。

在types检查阶段,假设编译器确定foo没有双参数bar方法,但它确实有一个单参数bar方法,其签名与元组解释兼容。 由于没有其他有效的解释,它假定这是你的意思,并将两个参数转换成一个元组。 请注意,如果有两个参数的bar方法,即使是一个与实际参数不兼容的方法,typer 也不会执行自动tupling转换。

一个声明,在调用arg函数时可以省略parens并不总是如此。 注意:

  println "hello" val puts = (s: String) => println(s) puts "hello" 

也不pipe用,尽pipe这里没有元组。 它使用中缀符号。 以下陈述很好:

  Console println "hello" val t = (1, 2) Console println t puts apply "hello" // puts is defined above