Почему это исключение переполнения стека? - PullRequest
4 голосов
/ 09 июня 2011

... несмотря на то, что он оптимизирован для хвостового вызова?

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)
}

Есть ли способ заставить компилятор Scala выполнять здесь оптимизацию хвостового вызова?

Ответы [ 2 ]

6 голосов
/ 09 июня 2011

Спасибо pst за комментарий о @tailrec.Учитывая, что сообщение об ошибке компиляции аннотации scala объясняет причину неоптимизации метода.

<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 =

при закрытом методе сортируется

Я подозреваю, что на уровне байтового кода есть дваинструкции для вызова методов: virtual_call и tail_call.

1 голос
/ 10 июня 2011

Любой, кто пытается воссоздать ошибку компилятора в REPL, должен заключить метод в класс следующим образом:

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)
}
}

Если вы просто подключите метод к REPL, это будет TCOвсе в порядке, так как метод вне класса не может быть переопределен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...