Scala在调用一个arg函数时为什么以及如何特别处理元组?
讨论Scala如何创建元组以绑定到一个arg函数。这导致Scala在调用一个arg函数时为什么以及如何特别处理元组?,scala,tuples,Scala,Tuples,讨论Scala如何创建元组以绑定到一个arg函数。这导致 scala> println(1, 2) (1,2) 答案是编译器允许在没有参数的情况下调用one-arg函数,因此从逻辑上讲,这是对带有元组的println的调用 但是不能使用单个元组参数调用println scala> val t = (1, 2) t: (Int, Int) = (1,2) scala> println t <console>:6: error: value t is not a m
scala> println(1, 2)
(1,2)
答案是编译器允许在没有参数的情况下调用one-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
^
scala>valt=(1,2)
t:(Int,Int)=(1,2)
scala>println t
:6:错误:值t不是单元的成员
println t
^
所以还有别的事情发生了。为什么元组在这里很特殊?调用arg函数时可以省略paren的语句并不总是正确的。 请注意:
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
与此相反,Scala解析println(1,2)
(或控制台println(1,2)
)的方式与解析任何两个参数方法调用的方式相同。稍后,编译器通过将方法参数包装在元组中以匹配实际的方法类型签名来转换调用
如果编译器没有这样做,像Console println(1,2)
这样完全有效的表达式将无法编译,因为println
不接受多个参数。对于这种行为,也有很多原因
从编译器的角度考虑像foobar(1,2)
这样的表达式,记住Scala有特殊的语法,允许您在方法调用中删除
和paren。这可能是对具有参数1
和2
的双参数bar
方法的调用,也可能是对具有单元组值参数的单参数bar
方法的调用。解析器不知道关于bar
方法的任何信息,因此它只是作为两个参数的方法调用进行解析
在类型检查阶段,假设编译器确定
foo
没有双参数bar
方法,但它确实有一个单参数bar
方法,其签名与元组解释兼容。由于没有其他有效的解释,它假定这就是您的意思,并将两个参数转换为一个元组。请注意,如果有一个双参数bar
方法,即使是与实际参数不兼容的方法,打字机也不会执行自动元组转换。请参阅,因此元组大小写是特殊的,因为编译器会以这种方式对其进行解析-但为什么?我看到了下面的答案,谢谢。当我发现我在使用中缀时也只能省略paren时,我有点惊讶,因为这似乎使一些DSL有点僵硬,例如结果应该等于(42)
,但我想解析器可能需要一些帮助。但是这仍然不能解释元组是如何被绑定的……因此,据我所知,编译器并没有使用no-parens的情况,而是使用parens的情况,稍后将参数列表转换为元组以匹配println(o:Any)
此外,对元组的转换允许编写采用变量参数的函数。不,变量参数是不相关的。我将编辑答案,让它更清楚。我应该说的不是变量参数,而是任何算术的函数,而不是写它们,什么,操纵它们?