Я пытаюсь выполнить некоторые операции, которые прямо сейчас могут вызвать StackOverflow в Котлине.
Зная это, я вспомнил, что в Kotlin есть поддержка tailrec
функций, поэтому я попытался сделать:
private tailrec fun Turn.debuffPhase(): List<Turn> {
val turns = listOf(this)
if (facts.debuff == 0 || knight.damage == 0) {
return turns
}
// Recursively find all possible thresholds of debuffing
return turns + debuff(debuffsForNextThreshold()).debuffPhase()
}
К моему удивлению, что IDEA не распознала его как tailrec
, я попытался отменить функцию расширения и сделать ее обычной функцией:
private tailrec fun debuffPhase(turn: Turn): List<Turn> {
val turns = listOf(turn)
if (turn.facts.debuff == 0 || turn.knight.damage == 0) {
return turns
}
// Recursively find all possible thresholds of debuffing
val newTurn = turn.debuff(turn.debuffsForNextThreshold())
return turns + debuffPhase(newTurn)
}
Даже так не принято. Важно не то, что последний вызов функции относится к той же функции? Я знаю, что +
является знаком функции List
plus
, но должно ли это иметь значение? Все примеры, которые я вижу в Интернете для хвостового вызова для других языков, допускают такие действия.
Я пытался сделать это и с Int
, это казалось более распространенным, чем добавление в списки, но имело тот же результат:
private tailrec fun discoverBuffsNeeded(dragon: RPGChar): Int {
val buffedDragon = dragon.buff(buff)
if (dragon.turnsToKill(initKnight) < 1 + buffedDragon.turnsToKill(initKnight)) {
return 0
}
return 1 + discoverBuffsNeeded(buffedDragon)
}
Разве все эти реализации не должны допускать хвостовой вызов? Я думал о некоторых других способах решить эту проблему (например, передать список как MutableList
в параметрах), но, когда это возможно, я стараюсь избегать отправки коллекций для изменения внутри функции, и это похоже на случай, когда это должно быть возможно.
PS: Что касается программы вопросов, я реализую решение для этого проблема.