На этом шаге мы рассмотрим задание встроенных функций.
Лямбды полезны, потому что дают больше свободы при написании программ. Однако за свободу нужно платить.
Когда вы объявляете лямбду, она представляется в 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 функции, которые принимают лямбды в аргументах, - это хорошая практика. Но иногда это невозможно. Примером, когда невозможно использовать встраивание, может служить рекурсивная функция, принимающая лямбду, потому что в результате встраивания такой функции получится бесконечный цикл копирования и вставки тела функции. компилятор предупредит вас, если вы попытаетесь встроить функцию с нарушением правил.
На следующем шаге мы рассмотрим ссылку на функцию.