当在第二个参数集中请求函数时,Scala编译器抱怨“对重载定义的模糊引用”

时间:2013-08-08 14:59:41

标签: function scala compiler-construction functional-programming signature

这看起来很奇怪。以下编译正常:

def foo(s: String) = "balsh"
def foo(s: String)(s2: String) = "kahsd"

如果我隐含了第二个参数,它仍然可以正常编译。

但是,以下情况不会:

def foo(s: String) = "bjda"
def foo(s: String)(fun: String => String) = fun(s)

^由于“对重载定义的模糊引用”,将无法编译。

我最初的想法是Scala将函数转换为Java的方式导致两者的签名相同。但是,看看编译编码(对于第二个函数,因为它不能用两者编译)和javap,你会看到这样的函数实际上被转换成:

public java.lang.String foo(java.lang.String, scala.Function1);

因此创建了一个具有不同签名的单独方法。那为什么这不能编译?

现在让问题更加令人困惑,以下实际上编译得很好!

def foo(s: String) = "bjda"
def foo(s: String, fun: String => String) = fun(s)

如果你把功能作为第一组参数的一部分,那么一切都很好!

有谁知道为什么会这样?

编辑:

所以我试过这个:

object main {
  def write(s: String) = "sasd"
  def write(s: String)(implicit s2: String => String) = s2(s)
}

我只是在隐含的第二个参数中创建了该函数。瞧,这是编译。

这是它生成的java代码:

public final class main$ extends java.lang.Object{
    public static final main$ MODULE$;
    public static {};
    public java.lang.String write(java.lang.String);
    public java.lang.String write(java.lang.String, scala.Function1);
}

这是我原本期望的,没有隐含的!

2 个答案:

答案 0 :(得分:0)

我猜测编译器无法在两者之间进行选择,因为它们实际上只是在返回类型上有所不同。基于函数的返回类型仅调度参数是不可能的。想想这样的签名:

def foo(s: String): String
def foo(s: String): String => String

不确定为什么你让它工作如果你隐含,我得到同样的错误(如我所料)。

def foo(s: String, fun: String => String) 
另一方面,

有一个不同的参数列表,可以发送到。

答案 1 :(得分:0)

如果有人想避免隐含的黑客行为,这是另一种方式:

def foo(s: String) = "balsh"
def foo(t: String)(s2: String) = "kahsd"

其中第二个函数的参数名称更改为不同的名称。然后,当你想要第一个:

foo(s = "foo")

当你想要第二个时:

foo(t = "foo")