Ответ
crossinline используется в inline функциях для запрета нелокального возврата (return) из лямбды, переданной в такую функцию.
Проблема:
В обычной inline функции return внутри лямбды завершает внешнюю функцию, что может быть неожиданно:
inline fun runInline(block: () -> Unit) {
block()
}
fun main() {
runInline {
println("Before return")
return // Неожиданно завершает main()
}
println("This won't execute")
}
Решение:
Добавляем crossinline, чтобы запретить return:
inline fun runCrossInline(crossinline block: () -> Unit) {
block()
}
fun main() {
runCrossInline {
println("Before return")
// return // Ошибка компиляции: Can't return here
}
println("This will execute")
}
Где используется:
Чаще всего в асинхронных вызовах (например, view.post { ... }), где нелокальный return нарушил бы логику.
Ответ 18+ 🔞
А, ну это про crossinline! Слушай, тут история простая, но если не вникнуть — можно ебушки-воробушки получить.
Вот смотри: есть у нас inline функции. Они, блядь, хорошие — производительность улучшают, потому что код вставляется прямо на место вызова, а не вызывается как отдельная функция. Но есть у них одна хитрая жопа: если ты в лямбде внутри такой функции напишешь return, то он выйдет не только из лямбды, а из всей внешней функции, которая эту inline-функцию вызвала. Представляешь?
inline fun runInline(block: () -> Unit) {
block()
}
fun main() {
runInline {
println("Перед возвратом")
return // Ёпта! Этот return завершит всю функцию main()!
}
println("А эта строка уже не выполнится") // Сюда мы никогда не попадём
}
Вот это пиздец, да? Ты думаешь, что возвращаешься из лямбды, а на самом деле — бац, и вся твоя программа накрылась медным тазом. Удивление пиздец, когда такое впервые встречаешь.
И вот тут на сцену выходит наш спаситель — crossinline. Это модификатор, который ты вешаешь на параметр-лямбду. Он говорит компилятору: "Чувак, эту лямбду всё равно inline'ь, но запрети в ней нелокальные returnы! Пусть возвращается только внутри себя, как нормальная лямбда".
inline fun runCrossInline(crossinline block: () -> Unit) {
block()
}
fun main() {
runCrossInline {
println("Перед возвратом")
// return // Ошибка компиляции! Нельзя тут! Can't return here
// Можно только return@runCrossInline — локальный возврат к метке
}
println("А эта строка благополучно выполнится") // Всё работает!
}
Где это, блядь, нужно? Да везде, где лямбда выполняется не прямо сейчас, а потом. Например, ты передаёшь её в какой-нибудь асинхронный вызов типа view.post { ... }. Представь: функция post отработала и завершилась, а твоя лямбда выполнится только через 16 миллисекунд, когда придёт следующий кадр отрисовки. Какой нахуй return из внешней функции может быть в этом случае? Внешняя функция уже давно завершилась! Это же бред, ёперный театр. Вот crossinline и спасает от таких граблей.
Короче, запомни: хочешь запретить return, который выпрыгивает из лямбды наружу — добавляй crossinline. Всё просто, как три копейки.