Scala 和尾递归
Stack Overflow 上有各种答案,解释了 Scala< 中可以进行尾递归的条件/a>.我了解其局限性以及如何以及在何处可以利用尾递归。我不明白的是为什么存在对私有或最终方法的限制。
我还没有研究 Scala 编译器实际上如何在字节码级别将递归函数转换为非递归函数,但我们假设它执行如下操作。我有一个带有递归函数 mod
的类 Foo
:
class Foo {
def mod(value: Int, denom: Int): Int = {
if(denom <= 0 || value <= 0) 0
else if(0 <= value && value < denom) value
else mod(value - denom, denom)
}
}
这是一个基本的模函数,我想 Scala 编译器会将其转换为某种伪 Java-Scala,例如:(
class Foo {
def mod(value: Int, denom: Int): Int = {
if(denom <= 0 || value <= 0) return 0
while(value > denom) value -= denom
return value
}
}
我可以相信我搞砸了翻译,但我认为细节并不重要..)
所以现在假设我子类 Foo
:
class Bar extends Foo {
def mod(value:Int, denom: Int): Int = 1
}
是什么阻止了它的工作?当JVM有一个Foo/Bar
并且对其调用mod
时,为什么解析应该使用的mod
函数会出现问题。为什么这与基函数非递归的情况有什么不同?
我可以看到出现这种情况的几个可能的原因是:
无论出于何种原因,Scala 编译器的实现都无法处理此问题(如果是这种情况,那就很公平了。如果是这样,是否有计划对此进行更改? )
in
Foo
mod
函数在编译期间被修改为mod-non-recursive
,因此Foo
实际上没有mod
> 要重写的方法。
There are various answers on Stack Overflow which explain the conditions under which tail recursion is possible in Scala. I understand the limitations and how and where I can take advantage of tail recursion. The part I don't understand is why the limitation to private or final methods exists.
I haven't researched how the Scala compiler actually converts a recursive function to a non-recursive one at a bytecode level, but let's assume it does something like the following. I have a class Foo
with a recursive function mod
:
class Foo {
def mod(value: Int, denom: Int): Int = {
if(denom <= 0 || value <= 0) 0
else if(0 <= value && value < denom) value
else mod(value - denom, denom)
}
}
That's a basic modulo function which I imagine the Scala compiler translates to some kind of pseudo-Java-Scala like:
class Foo {
def mod(value: Int, denom: Int): Int = {
if(denom <= 0 || value <= 0) return 0
while(value > denom) value -= denom
return value
}
}
(I can believe I've messed up that translation but I don't think the details are important..)
So now suppose I subclass Foo
:
class Bar extends Foo {
def mod(value:Int, denom: Int): Int = 1
}
What it is that stops this from working? When the JVM has a Foo/Bar
and mod
is called on it, why is there a problem with resolving the mod
function that should be used. Why is this any different from the situation where the base function is non-recursive?
A few possible reasons I can see for this being the case are:
for whatever reason the implementation of the Scala compiler doesn't handle this (fair enough if that is the case. If so, are there plans to change this?)
in
Foo
themod
function is munged tomod-non-recursive
during compilation soFoo
doesn't actually have amod
method to override.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我刚刚回答了这个问题,但让我们举个你自己的例子。假设您定义了 Foo 类,并将其作为 JAR 文件提供。
然后我获取该 Jar 文件,并以这种方式扩展您的 Foo:
现在,当 Foo 的
mod
调用自身时,因为我的对象是Bar
,而不是Foo< /code>,你应该(并且确实)去 Bar's
mod
,而不是 Foo's。因为这是事实,所以您无法按照您所展示的方式对其进行优化。
子类化的契约是,当超类调用自身的方法时,如果该方法已被重写,则将调用子类的方法。
将方法声明为私有,使其成为最终方法或类,甚至创建一个递归函数而不是方法,所有这些都确保您不必使用子类实现。
I have just answered that, but let's take your own example. Say you defined that class Foo, and made it available as a JAR file.
Then I get that Jar file, and extend your Foo this way:
Now, when Foo's
mod
calls itself, because my object is aBar
, not aFoo
, you are supposed (and do) go to Bar'smod
, not to Foo's.And because that is true, you can't optimize it the way you have shown.
It is the CONTRACT of subclassing that, when a super class calls a method on itself, if that method has been overridden it will be the subclass' method to be invoked.
Declaring the method private, making it final, or the class -- or even making a recursive function instead of a method, all insure you won't potentially have to go to a subclass implementation.
IttayD 今天早些时候刚刚问过这个问题。答案是,只有当你不能在子类中重写 mod 时,Foo 的尾递归才会被优化 (因为类是最终的,或者因为方法是最终的或私有的。)
IttayD just asked this question earlier today. The answer is that Foo's tail recursion will only be optimized if you can't override mod in subclasses (be that becuase the class is final, or because the method is final or private.)