Scala 模糊性与无括号函数调用

Posted

技术标签:

【中文标题】Scala 模糊性与无括号函数调用【英文标题】:Scala ambiguity with paren-less function calls 【发布时间】:2015-10-01 00:36:32 【问题描述】:

请原谅长时间的设置。这个问题与Scala: ambiguous reference to overloaded definition - best disambiguation? 相关,但没有得到回答。

我对 Scala 还是很陌生,让我失望的一件事是 Scala:

具有一流的功能 在使用没有任何括号参数列表的对象点表示法时调用函数(就像函数是一个属性一样)

这两种语言特性让我很困惑。看下面的代码:

我的班级 def something(in: String): String = 在 + "_X" 定义一些东西:字符串 => 字符串 = 案例_ =>“固定” val my = new MyClass() println(List("foo", "bar").map(my.something))

我希望通过调用与map 所需的String => ? 参数匹配的something 原型来打印List("foo_X", "bar_X")。相反,输出是List("Fixed", "Fixed") - Scala 2.11 调用无参数something(),然后将其返回值传递给map

如果我们注释掉 something 的第二个无参数原型,输出将变为预期结果,证明另一个原型在上下文中是有效的。

向第二个原型添加一个空参数列表(使其成为def something())也会改变行为。

my.something 更改为 my.something(_) 会使 Scala 意识到它之前默默忽略的模棱两可:

错误:对重载定义的模糊引用, 两种方法都属于 MyClass 类型的方法 => String => String 和方法类 MyClass 类型的东西(in:String)String 匹配参数类型(字符串) println(List("foo", "bar").map(my.something(_)))

即使使用据说是为此目的的魔术尾随下划线也不起作用:

val myFun: (String) => String = my.something _

这会导致:

错误:类型不匹配; 发现:()=>字符串=>字符串 必需:字符串 => 字符串 val myFun: (String) => String = my.something _

我的问题:

如果我的 MyClass 与所写的完全相同(原型没有更改,尤其是没有向其中一个原型添加空参数列表),我如何明确地告诉 Scala 我想要第一个单参数版本something 作为参数传递给另一个调用? 既然显然有两个令人满意的参数可以传递给 map,为什么 Scala 编译器没有将歧义报告为错误? 有没有办法禁用 Scala 将 foo.bar 视为等同于 foo.bar() 的行为(有时,并非总是如此)?

【问题讨论】:

这在 Atomic Sc​​ala 中的“A Bit of Style”一章中进行了讨论。如果一个方法没有参数,它可以用括号定义,也可以不用括号。如果它是用括号定义的,则可以带或不带括号来调用它。但是,如果定义时不带括号,则只能在不带括号的情况下调用它。一个风格约定是如果调用它们会改变对象的内部状态,则使用括号定义方法,否则定义它们时不使用括号。在您设计的示例中,编译器似乎已尽力根据包括括号在内的签名选择正确的函数。 【参考方案1】:

我已经在 Scala 问题跟踪器上提交了一个错误,并且共识似乎是这种行为是一个错误。编译器应该抛出一个关于“my.something”的模糊引用的错误。

【讨论】:

github.com/scala/bug/issues/9395 没有达成共识,但有回复。 Dotty 并不模棱两可,而是选择了方法。什么?

以上是关于Scala 模糊性与无括号函数调用的主要内容,如果未能解决你的问题,请参考以下文章

Scala方法调用中的花括号[重复]

scala map 后加小括号和大括号的区别

Scala的柯里化和函数的部分施用

Scala Class etc. 2

scala中的传名调用

Scala函数的调用