开发者

Why is this throwing stack overflow exception?

开发者 https://www.devze.com 2023-03-12 00:05 出处:网络
... despite it being tail-call-optimizable? def areStreamsEqual(stream1: InputStream, stream2: InputStream): Boolean =

... despite it being tail-call-optimizable?

def areStreamsEqual(stream1: InputStream, stream2: InputStream): Boolean =
{
    val one = stream1.read()
    val two = stream2.read()
    if(one != two)
        false
    else if(one == -1 && 开发者_如何学编程two == -1)
        true
    else
        areStreamsEqual(stream1, stream2)
}

Is there anyway to force the Scala compiler to do a tail call optimization here?


Thanks to pst for the comment about @tailrec. Given that annotation scala compiler error message explains the reason for not optimizing the method.

<filename>.scala:64: error: could not optimize @tailrec annotated method: it is neither private nor final so can be overridden
def areStreamsEqual(stream1: InputStream, stream2: InputStream): Boolean =

making the method private sorts it out

I suspect that on the byte code level, there are two instructions for calling methods: virtual_call and tail_call.


For anyone trying to recreate the compiler error in the REPL, you have to wrap the method in a class like this:

class Test {
@annotation.tailrec def areStreamsEqual(stream1: InputStream, stream2: InputStream): Boolean =
{
    val one = stream1.read()
    val two = stream2.read()
    if(one != two)
        false
    else if(one == -1 && two == -1)
        true
    else
        areStreamsEqual(stream1, stream2)
}
}

If you just plug the method into the REPL, it will be TCO'd just fine, since the method outside of a class can't be overridden.

0

精彩评论

暂无评论...
验证码 换一张
取 消