soc*_*soc 132 methods default scala overloading
虽然可能存在这样的方法过载可能变得模糊的有效情况,但为什么编译器不允许在编译时和运行时都不模糊的代码?
例:
// This fails:
def foo(a: String)(b: Int = 42) = a + b
def foo(a: Int) (b: Int = 42) = a + b
// This fails, too. Even if there is no position in the argument list,
// where the types are the same.
def foo(a: Int) (b: Int = 42) = a + b
def foo(a: String)(b: String = "Foo") = a + b
// This is OK:
def foo(a: String)(b: Int) = a + b
def foo(a: Int) (b: Int = 42) = a + b
// Even this is OK.
def foo(a: Int)(b: Int) = a + b
def foo(a: Int)(b: String = "Foo") = a + b
val bar = foo(42)_ // This complains obviously ...
Run Code Online (Sandbox Code Playgroud)
是否有任何理由不能放松这些限制?
特别是在将重载过多的Java代码转换为Scala时,默认参数是非常重要的,在通过一个Scala方法替换大量Java方法之后发现规范/编译器强加任意限制并不好.
Eug*_*bun 107
我想引用Lukas Rytz(来自这里):
原因是我们想要一个返回默认参数的生成方法的确定性命名方案.如果你写
def f(a: Int = 1)
编译器生成
def f$default$1 = 1
如果在同一参数位置有两个默认值的重载,我们需要一个不同的命名方案.但是我们希望在多个编译器运行中保持生成的字节码稳定.
未来Scala版本的解决方案可能是将非默认参数的类型名称(方法开头的那些,将歧义重载的版本消除歧义)合并到命名模式中,例如在这种情况下:
def foo(a: String)(b: Int = 42) = a + b
def foo(a: Int) (b: Int = 42) = a + b
Run Code Online (Sandbox Code Playgroud)
它会是这样的:
def foo$String$default$2 = 42
def foo$Int$default$2 = 42
Run Code Online (Sandbox Code Playgroud)
有人愿意写一个SIP提案吗?
Mar*_*sky 66
对于重载分辨率与默认参数的交互,获取可读且精确的规范将非常困难.当然,对于许多个别情况,例如这里介绍的情况,很容易说出应该发生什么.但这还不够.我们需要一个决定所有可能的极端情况的规范.重载分辨率已经非常难以指定.在混合中添加默认参数会使其更难.这就是我们选择将两者分开的原因.
Lan*_*dei 11
我无法回答你的问题,但这是一个解决方法:
implicit def left2Either[A,B](a:A):Either[A,B] = Left(a)
implicit def right2Either[A,B](b:B):Either[A,B] = Right(b)
def foo(a: Either[Int, String], b: Int = 42) = a match {
case Left(i) => i + b
case Right(s) => s + b
}
Run Code Online (Sandbox Code Playgroud)
如果你有两个非常长的arg列表,只有一个arg不同,那么它可能值得一试......
对我有用的是重新定义(Java风格的)重载方法。
def foo(a: Int, b: Int) = a + b
def foo(a: Int, b: String) = a + b
def foo(a: Int) = a + "42"
def foo(a: String) = a + "42"
Run Code Online (Sandbox Code Playgroud)
这样可以确保编译器根据当前参数所需的分辨率。