Scala 3 中使用 Varargs 的模糊重载
Ambiguous Overload in Scala 3 with Varargs
我有以下代码。
object example {
def foo(a: Any) = "Object"
def foo(a: String, args: String*) = "String"
def main() = {
println(foo("ABC")) // Should print "String"
}
}
在 Scala 2 中,这段代码工作正常。当我用一个字符串参数调用 foo
时,两个重载都是有效的,但 String
一个更具体,所以它被调用。在 Scala 3 中,这是不明确的。
-- [E051] Reference Error: overloads.scala:9:12 --------------------------------------------------------------------
9 | println(foo("ABC"))
| ^^^
| Ambiguous overload. The overloaded alternatives of method foo in object example with types
| (a: String, args: String*): String
| (a: Any): String
| both match arguments (("ABC" : String))
等效代码(两个重载,其中一个更具体并且具有 vararg 参数)也适用于 Java。 Scala 3 中到底发生了什么变化,使这个特定的调用变得模棱两可?这种行为是故意的吗?在这种情况下,我如何告诉 Scala 调用哪个重载?
就其价值而言,我很清楚在 Scala 中强烈反对方法重载。在我的实际代码中,我正在与具有重载 .append
方法的 Java 构建器 class 交互,因此我无法控制函数签名。
this PR, in particular in this comment 中提到了此行为。我不知道这是否会“修复”或者是否完全符合预期。
注意以下不是歧义:
def foo(s: String)
def foo(a: String, other: String*)
foo("fine!")
使用 def foo(s: Any)
,您可以显式 select 一个重载或另一个重载,如下所示:
foo("fine": Any) // calls foo(Any)
foo("fine", Nil: _*) // calls foo(String, String*) with an empty vararg
PS:我不会说重载是“强烈反对”的,但我们必须小心并承认某些情况对编译器和人类来说是模棱两可的。对我来说,foo("")
应该指的是哪个定义并不明显,所以在这种情况下更明确一点并不完全疯狂。
我有以下代码。
object example {
def foo(a: Any) = "Object"
def foo(a: String, args: String*) = "String"
def main() = {
println(foo("ABC")) // Should print "String"
}
}
在 Scala 2 中,这段代码工作正常。当我用一个字符串参数调用 foo
时,两个重载都是有效的,但 String
一个更具体,所以它被调用。在 Scala 3 中,这是不明确的。
-- [E051] Reference Error: overloads.scala:9:12 --------------------------------------------------------------------
9 | println(foo("ABC"))
| ^^^
| Ambiguous overload. The overloaded alternatives of method foo in object example with types
| (a: String, args: String*): String
| (a: Any): String
| both match arguments (("ABC" : String))
等效代码(两个重载,其中一个更具体并且具有 vararg 参数)也适用于 Java。 Scala 3 中到底发生了什么变化,使这个特定的调用变得模棱两可?这种行为是故意的吗?在这种情况下,我如何告诉 Scala 调用哪个重载?
就其价值而言,我很清楚在 Scala 中强烈反对方法重载。在我的实际代码中,我正在与具有重载 .append
方法的 Java 构建器 class 交互,因此我无法控制函数签名。
this PR, in particular in this comment 中提到了此行为。我不知道这是否会“修复”或者是否完全符合预期。
注意以下不是歧义:
def foo(s: String)
def foo(a: String, other: String*)
foo("fine!")
使用 def foo(s: Any)
,您可以显式 select 一个重载或另一个重载,如下所示:
foo("fine": Any) // calls foo(Any)
foo("fine", Nil: _*) // calls foo(String, String*) with an empty vararg
PS:我不会说重载是“强烈反对”的,但我们必须小心并承认某些情况对编译器和人类来说是模棱两可的。对我来说,foo("")
应该指的是哪个定义并不明显,所以在这种情况下更明确一点并不完全疯狂。