使用 Scala 的命令行 REPL:
def foo(x: Int): Unit = {}
def foo(x: String): Unit = {println(foo(2))}
gives
error: type mismatch;
found: Int(2)
required: String
看来你不能在 REPL 中定义重载的递归方法。我认为这是 Scala REPL 中的一个错误并提交了它,但它几乎立即被关闭,并显示“wontfix:考虑到解释器的语义,我看不出有任何方式可以支持它,因为必须编译这两个方法一起。”他建议将这些方法放在一个封闭的对象中。
有 JVM 语言实现或 Scala 专家可以解释原因吗?我可以看到,如果这些方法互相调用,例如,这将是一个问题,但在这种情况下呢?
或者,如果这是一个太大的问题,并且您认为我需要更多先决知识,是否有人有关于语言实现(尤其是 JVM)的书籍或网站的良好链接? (我知道 John Rose 的博客和《编程语言语用学》一书……仅此而已。:)
问题是由于口译员通常必须replace具有给定名称的现有元素,而不是重载它们。例如,我经常会尝试一些东西,经常创建一个名为test
:
def test(x: Int) = x + x
稍后,假设我正在运行一个不同的实验,我创建了另一个名为test
,与第一个无关:
def test(ls: List[Int]) = (0 /: ls) { _ + _ }
这并不是一个完全不现实的场景。事实上,这正是大多数人使用口译员的方式,通常甚至没有意识到。如果解释器任意决定保留两个版本test
在范围内,这可能会导致使用测试时出现令人困惑的语义差异。例如,我们可能会打电话给test
,不小心路过Int
而不是List[Int]
(这不是世界上最不可能发生的事故):
test(1 :: Nil) // => 1
test(2) // => 4 (expecting 2)
随着时间的推移,解释器的根作用域会变得非常混乱,充满了各种版本的方法、字段等。我倾向于让我的解释器一次打开几天,但如果允许这样的重载,我们将被迫“当事情变得太混乱时,经常刷新”口译员。
这不是 JVM 或 Scala 编译器的限制,而是经过深思熟虑的设计决策。正如错误中提到的,如果您位于根范围之外的其他范围内,您仍然可以重载。对我来说,将测试方法封装在一个类中似乎是最好的解决方案。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)