Для чего нужен noinline

Ответ

noinline — это модификатор в Kotlin, который указывает компилятору не встраивать лямбда-выражение, переданное в функцию с модификатором inline.

Когда использовать:

  • Если лямбда передается в другую функцию (не inline).
  • Если нужно сохранить ссылку на лямбду (например, для отложенного выполнения).

Пример:

inline fun executeTask(noinline task: () -> Unit) {  
    // task нельзя встроить, так как он передается дальше  
    runLater(task)  
}  

fun runLater(action: () -> Unit) {  
    // выполнение action  
}  

Без noinline компилятор выдаст ошибку, так как inline-функция пытается передать лямбду в не-inline контекст.

Ответ 18+ 🔞

А, ну это про noinline! Давай разжую, как бабушка котлету, чтоб понятно было даже тому, кто вчера только с луны свалился.

Представь, что у тебя есть функция-заводила, которая всех зовёт на тусовку и сама всех рассаживает. Это inline-функция. Она не просто зовёт — она прямо на месте, в коде, заменяет свой вызов содержимым. Быстро, эффективно, без лишних телодвижений.

А теперь смотри. Ты в этой функции-заводиле хочешь не просто вызвать переданную лямбду (задачу), а отложить её на потом — передать другому, положить в карман, записать в список дел. Вот тут-то и начинается ёперный театр.

Компилятор смотрит на это и говорит: «Чувак, ты чего? Я тут всё оптимизирую, всё встраиваю, а ты у меня лямбду куда-то в сторону пихаешь! Так не пойдёт. Я не могу встроить то, что потом должно жить отдельной жизнью!»

И вот тут ты вытаскиваешь волшебный ключ — модификатор noinline. Ты им помечаешь конкретный параметр-лямбду и говоришь компилятору: «Э, сабака сука, э бошка думай! Эту вот конкретно — не трогай, оставь как есть, как отдельную сущность. А всё остальное — давай, встраивай, оптимизируй».

Проще говоря:

  • inline — «сделай всё прямо здесь и сейчас».
  • noinline (на конкретном параметре) — «а вот эту штуку — не трогай, она мне ещё нужна целая».

Твой пример — идеальный случай. Функция executeTask объявлена как inline, потому что, наверное, часть своей работы она делает сразу. Но параметр task помечен как noinline, потому что его нельзя «размазать» по коду — его нужно передать целиком в другую функцию runLater, которая про inline ничего не знает. Без noinline компилятор бы просто взвыл от ошибки, потому что не может совместить несовместимое.

Когда это нужно, кроме отложенного вызова?

  • Когда ты сохраняешь лямбду в свойство класса.
  • Когда передаёшь её в какую-нибудь коллекцию.
  • Когда вообще делаешь с ней что-то, что требует, чтобы она осталась полноценным объектом, а не куском встроенного кода.

Запомни: noinline — это не отмена inline для всей функции. Это точечное указание: «вот этого парня — не встраивай, а всё остальное — давай». Удобная штука, когда нужно и рыбку съесть (оптимизацию), и на хуй сесть (сохранить ссылку на лямбду).