Привыкайте писать вместе! Это 13-й день моего участия в «Новом ежедневном плане Nuggets · Апрельское задание по обновлению», нажмите, чтобы просмотреть подробности мероприятия .
1. Оптимизация хвостовой рекурсии
Обычно мы можем столкнуться со сценарием написания рекурсивных функций, таких как:
fun test5(n: Int): Int =
if (n == 1) {
1
} else
test5(n - 1)
复制代码
Каждый метод соответствует фрейму стека. Рекурсивный вызов метода приведет к тому, что глубина стека метода будет слишком большой, и существует риск OOM. Kotlin обеспечивает 尾递归特性
оптимизацию:
tailrec fun test5(n: Int): Int =
if (n == 1) {
1
} else
test5(n - 1)
复制代码
Видно, что оптимизация хвостовой рекурсии заключается в добавлении в метод tailrec
, а вызов рекурсивного метода должен быть в конце метода, декомпилируйте его в java-код, чтобы увидеть эффект:
Вы можете видеть, что компилятор оптимизирует рекурсивный вызов метода.
infix
2. Реальная борьба инфиксного метода
Модификация инфиксного метода заключается в добавлении infix
объявления к методу, при этом может быть объявлен только один параметр метода, например:
infix fun String.a(b: String) = "$this - $b"
复制代码
Поясним на примере:
У нас обычно есть такое требование:传入文件路径String返回File类型
fun makeFile(parent: String, child: String): File {
return File(parent, child)
}
复制代码
В таком написании нет ничего плохого, но с помощью инфиксной функции мы можем добиться более элегантной инкапсуляции, как показано ниже:
infix fun String.div(child: String): File = File(this, child)
复制代码
Используйте следующим образом:
fun makeFile(parent: String, child: String): File = parent div child
复制代码
что parent div child
эквивалентно File(this, child)
реализации .
Это не особенно элегантно для написания, например, приходится каждый раз div
создавать File
объекты , div
это слишком громоздко для написания, а читабельность слишком плохая.
Чтобы решить две вышеупомянутые проблемы, мы можем объединить перегрузку операторов operator
для дальнейшей оптимизации.Давайте посмотрим на общие функции перегрузки операторов и отношения отображения соответствующих операторов:
выражение | перерабатывать |
---|---|
а + б | а. плюс (б) |
а - б | а.минус(б) |
а * б | раз (б) |
а/б | а.дел(б) |
а % б | а. мод (б) |
а..б | a.rangeTo (б) |
Среди них есть оператор div
перегрузки функции /
, с помощью которого мы преобразуем функцию String в File выше:
infix operator fun String.div(child: String): File = File(this, child)
复制代码
Затем его можно использовать следующим образом:
fun makeFile(parent: String, child: String): File = parent / child
复制代码
Как видно выше, parent / child
создание файла может быть выполнено напрямую, и /
читабельность выше.