Scala为什么以及如何在调用一个arg函数时特别处理元组?

时间:2011-05-13 20:42:28

标签: scala tuples

scala coalesces multiple function call parameters into a Tuple -- can this be disabled?讨论了Scala创建一个绑定到一个arg函数的元组。这导致

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

答案说编译器允许在没有parens的情况下调用一个arg函数,因此逻辑上这是对带有元组的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
           ^

所以其他事情正在发生。为什么元组在这里很特别?

2 个答案:

答案 0 :(得分:15)

相反,this explanation,Scala的解析 println(1,2)(或Console println (1,2)对于这个问题)它解析任何两个参数的方法调用的方法相同。稍后,编译器通过将方法参数包装在元组中来匹配实际的方法类型签名来转换调用。

如果编译器没有这样做,那么像Console println (1,2)这样完全有效的表达式将无法编译,因为println不会带多个参数。此行为也有other valid use cases

从编译器的角度考虑类似foo bar (1,2)的表达式,请记住Scala具有特殊的语法,允许您删除方法调用上的.和parens。这可能是对带有参数bar1的双参数2方法的调用,或者它可能是对单个参数bar方法的调用元组值论证。解析器对bar方法一无所知,因此它只是作为双参数方法调用进行解析。

在类型检查阶段,假设编译器确定foo没有两个参数bar的方法,但它确实有一个参数bar方法,其签名是兼容元组解释。由于没有其他有效的解释,它假定这是你的意思,并将两个参数转换为元组。请注意,如果有一个带两个参数bar方法中,即使一个是与实际参数,导电型测量仪的不会执行自动几倍转化。

不相容

答案 1 :(得分:0)

一个声明,你可以在调用on-arg函数时省略parens并不总是正确的。 请注意:

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

尽管这里没有元组,但也不起作用。 如果您使用中缀表示法,它可以工作。以下陈述非常有效:

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