Шаг 56.
Основы Kotlin.
Анонимные функции и функциональные типы. Встроенные функции

    На этом шаге мы рассмотрим задание встроенных функций.

    Лямбды полезны, потому что дают больше свободы при написании программ. Однако за свободу нужно платить.

    Когда вы объявляете лямбду, она представляется в JVM экземпляром объекта. JVM также выделяет память для всех переменных, доступных в лямбде, а это увеличивает расход памяти. Проще говоря, лямбды очень неэффективно расходуют память, что сказывается на производительности. А потерь производительности следует избегать.

    К счастью, есть возможность включить оптимизацию, которая избавит от чрезмерного расходования памяти при использовании лямбд в качестве аргументов. Такая возможность называется встраиванием (инлайнинг). Встраивание избавляет JVM от необходимости использовать экземпляр объекта и выделять память для переменных в лямбде.

    Чтобы встроить лямбду, отметьте функцию, принимающую лямбду, ключевым словом inline. Добавьте ключевое слово inline в определение функции runSimulation.

.   .   .   .   .
inline fun runSimulation(playerName: String, greetingFunction: (String, Int) -> 
    String) {
        val numBuildings = (1..3).shuffled().last() // Случайно выберет 1, 2 или 3
        println(greetingFunction(playerName, numBuildings))
}
Файл с проектом можно взять здесь.


Рис.1. Использование ключевого слова inline (SimVillage.kt)

    Теперь, когда вы добавили ключевое слово inline, вместо вызова runSimulation() с экземпляром объекта лямбды компилятор "скопирует и вставит" тело функции туда, откуда произведен вызов. Посмотрите на скомпилированный байт-код функции main() в SimVillage.kt, где происходит вызов функции runSimulation():


Рис.2. Скомпилированный байт-код функции main() в SimVillage.kt

    Обратите внимание, что вместо вызова функции runSimulation() в main() было вставлено тело runSimulation() вместе с лямбдой, благодаря чему отпала необходимость передавать лямбду (и создавать еще один экземпляр объекта).

    В целом, отмечать ключевым словом inline функции, которые принимают лямбды в аргументах, - это хорошая практика. Но иногда это невозможно. Примером, когда невозможно использовать встраивание, может служить рекурсивная функция, принимающая лямбду, потому что в результате встраивания такой функции получится бесконечный цикл копирования и вставки тела функции. компилятор предупредит вас, если вы попытаетесь встроить функцию с нарушением правил.

    На следующем шаге мы рассмотрим ссылку на функцию.




Предыдущий шаг Содержание Следующий шаг