Scala 在调用单参数函数时为什么以及如何特殊对待元组?

发布于 2024-11-07 07:22:16 字数 503 浏览 0 评论 0原文

scala 将多个函数调用参数合并到一个元组中 - 可以禁用此功能吗? 讨论了 Scala 创建一个元组以绑定到一个 arg 函数。这导致

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

答案说编译器允许在没有括号的情况下调用一个 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 coalesces multiple function call parameters into a Tuple -- can this be disabled? discusses Scala creating a tuple to bind to one arg function. This results in

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

The answer says that the compiler allows one arg functions to be called with no parens, so that logically this is a call to println with a tuple.

But println cannot be called with a single tuple parameter

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
           ^

so something else is going on. Why are tuples special here?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

冰火雁神 2024-11-14 07:22:16

相反这个解释,Scala解析 println(1,2)(或Console println (1,2))它以同样的方式解析任何双参数方法调用。随后,编译器通过将方法参数包装在元组中来转换调用,以匹配实际的方法类型签名。

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

从编译器的角度考虑像 foo bar (1,2) 这样的表达式,请记住 Scala 有特殊的语法,允许您删除 . 和括号在方法调用上。这可能是对带有参数 12 的双参数 bar 方法的调用,也可能是对单参数的调用带有单个元组值参数的 bar 方法。解析器对 bar 方法一无所知,因此它只是解析为两个参数的方法调用。

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

Contrary to this explanation, Scala parses println(1,2) (or Console println (1,2) for that matter) the same way it parses any two-argument method call. Later, the compiler transforms the call by wrapping the method arguments in a tuple to match the actual method type signature.

If the compiler did not do this, perfectly valid expressions like Console println (1,2) would fail to compile because println does not take multiple arguments. There are also other valid use cases for this behavior.

Consider an expression like foo bar (1,2) from the compiler's point of view, keeping in mind that Scala has special syntax that allows you to drop the . and the parens on method calls. This could be a call to a two-argument bar method with arguments 1 and 2, or it could be a call to a one-argument bar method with a single tuple-valued argument. The parser doesn't know anything about the bar method, so it just parses as a two-argument method call.

During the type checking phase, suppose the compiler determines that foo has no two-argument bar method but that it does have a one-argument bar method whose signature is compatible with the tuple interpretation. Since there is no other valid interpretation, it assumes that this is what you meant and transforms the two arguments into a tuple. Note that if there is a two-argument bar method, even one that is incompatible with the actual arguments, the typer will not perform the auto-tupling transformation.

国粹 2024-11-14 07:22:16

调用 on-arg 函数时可以省略括号的说法并不总是正确的。
请注意:

    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

A statement, that you can omit parens when calling on-arg function is not always true.
Note, that:

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

don't work either, despite that there's no tuple here.
It works if you use infix notation. Following statements work great:

    Console println "hello"
    val t = (1, 2)
    Console println t
    puts apply "hello" // puts is defined above
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文