, поскольку tailrec нельзя использовать в функциях расширения
Вы уверены?
Я только что проверил это, посмотрев байт-код Kotlin в IntelliJIDEA.Прежде всего, код с tailrec
в функции расширения успешно компилируется.Пойдем дальше: сравните две части кода Kotlin и байт-кода ниже, один с tailrec
, а другой без.
Kotlin:
fun Double.tailrecTestExtension(): Double
= (this - 1.0).tailrecTestExtension()
Байт-код:
// access flags 0x19
public final static tailrecTestExtension(D)D
// annotable parameter count: 1 (visible)
// annotable parameter count: 1 (invisible)
L0
LINENUMBER 13 L0
DLOAD 0
DCONST_1
DSUB
INVOKESTATIC com/example/TestKt.tailrecTestExtension (D)D
DRETURN
L1
LOCALVARIABLE $receiver D L0 L1 0
MAXSTACK = 4
MAXLOCALS = 2
Kotlin:
tailrec fun Double.tailrecTestExtension(): Double
= (this - 1.0).tailrecTestExtension()
Байт-код:
// access flags 0x19
public final static tailrecTestExtension(D)D
// annotable parameter count: 1 (visible)
// annotable parameter count: 1 (invisible)
L0
LINENUMBER 13 L0
DLOAD 0
DCONST_1
DSUB
DSTORE 0
GOTO L0
L1
LOCALVARIABLE $receiver D L0 L1 0
MAXSTACK = 4
MAXLOCALS = 2
Обратите внимание, что в первом примере есть вызов INVOKESTATIC
(что соответствует обычной рекурсии), который был заменен нарегулярный переход (GOTO
) во второй версии (что соответствует циклически ожидаемому поведению, введенному tailrec
).
Примечание: я не эксперт по байт-коду Kotlin, мое понимание основанона некоторые базовые знания о языке ассемблера.Здесь я предполагаю, что это знание может быть передано в байт-код Котлина.