Почему лямбда не может вернуть функцию включения? - PullRequest
0 голосов
/ 19 февраля 2019

Я совсем новичок в Котлине.Я нажал на эту часть, пока просматривал документы:

«лямбда не может вернуться из функции включения» (если она не встроена).

Итак, это не работает;

fun foo() {
    ordinaryFunction {
        return // ERROR: cannot make `foo` return here
    }
}

Интересно, почему это так работает?

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

Любая помощь будет отличной!

Ответы [ 3 ]

0 голосов
/ 19 февраля 2019

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

У Kotlin нет функции, позволяющей вам возвращаться из нескольких вызовов функции за один возврат,поэтому вы должны возвращаться из каждого вызова функции вручную.

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

0 голосов
/ 20 февраля 2019

могут быть некоторые дополнительные действия, которые может выполнять функция включения после выполнения лямбда-функции.

Проблема заключается в обратном: лямбда может "убежать" из функции включенияобласть действия и в конечном итоге выполняется после возврата функции.Например, рассмотрим

fun foo() {
    Thread(Runnable { 
        Thread.sleep(1000)
        return
    })
}

Или просто

 fun foo() = // lambda

В любом случае для лямбды нет смысла возвращаться из foo, не так ли?И компилятор не знает, позволяет ли ваш ordinaryFunction лямбда-экранировать область действия foo, если он не встроен.

вы можете преодолеть это, используя квалифицированные возвраты

Это не совсем преодоление, это просто не возврат из функции включения.

0 голосов
/ 19 февраля 2019

Проблема здесь в том, что нелокальный возврат не может быть выполнен на JVM .Если вы хотите вернуться из лямбды (местный возврат), вы можете добавить метку @ordinaryFunction:

fun foo() {
    ordinaryFunction {
        return@ordinaryFunction
    }
}

Документы , например:

Если нам нужноВозвращаясь к лямбда-выражению, мы должны пометить его и квалифицировать return.Часто бывает удобнее использовать неявные метки: такая метка имеет то же имя, что и функция, которой передается лямбда.В нашем случае это @ordinaryFunction.

...