Котлинская рекурсия

fun fact(x: Int): Int{
    tailrec fun factTail(y: Int, z: Int): Int{
        if (y == 0) return z
        else return factTail(y - 1, y * z)
    }
    return factTail(x, 1)
}

Может ли кто-нибудь объяснить мне, как приведенная выше функция рекурсии работает в kotlin?


person Ruby    schedule 30.10.2017    source источник
comment
tailrec в Kotlin предотвращает переполнение стека вашей функцией. Этот модификатор используется компилятором для его оптимизации.   -  person Nikola Despotoski    schedule 31.10.2017
comment
Мне нравится, как function factorial превращается в забавный факт на языке Kotlin.   -  person bipll    schedule 31.10.2017


Ответы (2)


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

Если мы избежим рекурсии, функция может выглядеть примерно так:

 fun fact(x: Int): Int {
    var result = x
    for (i in x - 1 downTo 1) {
        result *= i
    }
    return result
 }
person Giorgio Antonioli    schedule 30.10.2017

Существует большой риск, когда вы используете рекурсию в Java, которая представляет собой stackoverflow. стек

Как указано выше, рекурсия ссылок работает в Java. Для стека будет некоторый максимальный размер. Если наша функция рекурсии будет бесконечной, то она превысит максимальный размер, и это приведет к исключению StackOverflow. Поэтому избегайте использования рекурсии и вместо этого используйте цикл

Переходим к текущей проблеме. Это специальная рекурсия, которая называется Tail call. При этом функция должна вызывать себя как последнюю операцию, которую она выполняет. Хвостовые вызовы могут быть реализованы без добавления нового кадра стека в стек вызовов. Так что риска StackOverflow не будет. И это поддерживается в Котлине.

В Kotlin для отображения этой специальной рекурсии используется модификатор tailrec. Вы не можете использовать хвостовую рекурсию, когда после рекурсивного вызова есть еще код, и вы не можете использовать ее в блоках try/catch/finally.

person Asharali V U    schedule 28.11.2017
comment
Этот риск, о котором вы говорите, касается не только Котлина. - person Enzokie; 28.11.2017
comment
Это неверно, если у вас есть оптимизация хвостовой рекурсии, как в примере в исходном вопросе. - person dds; 13.05.2019
comment
Обновлен ответ - person Asharali V U; 16.05.2019