我正在查看FoldLeft和FoldRight方法,该方法的运算符版本非常奇特,就像这样(0 /:List.range(1,10))( + ) 。 对于具有两个参数列表的右关联函数,可以预期语法是这样的((param1)(param2)op HostClass)。 但在这种情况下它是语法(param1 op HostClass)(param2)。这导致了另一种情况的歧义,其中右关联函数返回另一个采用单个参数的函数。 由于这种歧义,类编译但是在进行函数调用时失败,如下所示。
class Test() {
val func1:(String => String) = { (in) => in * 2 }
def `test:`(x:String) = { println(x); func1 }
def `test:`(x:String)(y:String) = { x+" "+y }
}
val test = new Test
(("Foo") `test:` test)("hello")
<console>:10: error: ambiguous reference to overloaded definition,
both method test: in class Test of type (x: String)(y: String)String
and method test: in class Test of type (x: String)String => String
match argument types (String)
(("Foo") `test:` test)("hello")
所以我的问题是
这是预期的行为还是错误?
为什么两个参数列表右关联函数调用已经按照它的方式设计,而不是我认为更直观的语法((param1)(param2)op HostClass)?
是否有一种解决方法可以调用任何重载的test:function而不会产生歧义。
答案 0 :(得分:1)
Scala的类型系统仅考虑类型推断函数的第一个参数列表。因此,为了唯一地标识类或对象中的重载方法之一,方法的第一参数列表必须对于每个重载定义是不同的。这可以通过以下示例来说明。
object Test {
def test(x:String)(y:Int) = { x+" "+y.toString() }
def test(x:String)(y:String) = { x+" "+y }
}
Test.test("Hello")(1)
<console>:9: error: ambiguous reference to overloaded definition,
both method test in object Test of type (x: String)(y: String)String
and method test in object Test of type (x: String)(y: Int)String
match argument types (String)
Test.test("Hello")(1)
答案 1 :(得分:0)
它在运行时真的失败了吗?当我测试它时,类会编译,但方法test:
的调用不会。
我认为问题不在于操作符语法,而在于您有两个重载函数,一个只有一个,另一个有两个参数列表。
点符号会出现同样的错误:
test.`test:`("Foo")("hello")
如果重命名one-param list函数,则歧义将消失
(("Foo") `test:` test)("hello")
将编译。