【问题标题】:Right associative functions with two parameter list具有两个参数列表的右关联函数
【发布时间】:2015-03-31 05:09:53
【问题描述】:

我正在查看 FoldLeft 和 FoldRight 方法,该方法的操作符版本非常奇特,类似于 (0 /: List.range(1,10))(+) . 对于具有两个参数列表的右关联函数,人们会期望语法类似于 this((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) 语法?

是否有一种解决方法可以毫无歧义地调用任一重载测试:函数。

【问题讨论】:

  • 试试def test:(x:String, y:String) = { x+" "+y }

标签: scala


【解决方案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)

【讨论】:

    【解决方案2】:

    它真的在运行时失败吗?当我测试它时,该类可以编译,但是方法test:的调用没有。

    我认为问题不在于运算符语法,而在于您有两个重载函数,一个只有一个,另一个有两个参数列表。

    你会得到与点符号相同的错误:

    test.`test:`("Foo")("hello")
    

    如果你重命名单参数列表函数,歧义就会消失,

    (("Foo") `test:` test)("hello")
    

    将编译。

    【讨论】:

      猜你喜欢
      • 2012-02-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-11
      • 1970-01-01
      • 2020-07-01
      相关资源
      最近更新 更多