3

这似乎很奇怪。以下将编译正常:

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);
}

这就是我对没有隐含的原始版本所期望的!

4

2 回答 2

0

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

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

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

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

另一方面,有一个不同的参数列表,可以调度到。

于 2013-08-08T15:24:35.287 回答
0

如果有人想避免隐式破解,这里有另一种方法:

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

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

foo(s = "foo")

当你想要第二个时:

foo(t = "foo")
于 2015-06-16T01:22:35.230 回答