为什么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。 这可以是调用带参数1
和2
的双参数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