Kotlin Coroutines: Вызов отложенный :: ожидайте в последовательности :: карта - PullRequest
0 голосов
/ 25 ноября 2018

почему невозможно вызвать Deferred :: await в функции Sequence :: map, как это возможно в List :: map?

Я сделал небольшой пример

fun example() = runBlocking {

    val list = listOf(1, 2, 3, 4)

    list.map { async { doSomething(it) } }
            .map { it.await() }

    list.asSequence()
            .map { async { doSomething(it) } }
            .map { it.await() }         // Error: Kotlin: Suspension functions can be called only within coroutine body

}

Как видите, последнее утверждение не компилируется.

Ответы [ 2 ]

0 голосов
/ 25 ноября 2018

Добавление к ответу Марко, который является правильным:

Поскольку последовательность ленива, вызов await() может произойти после того, как runBlocking будет сделано, по сути.Ни асинхронный вызов, ни ожидание не произойдут, пока вы не начнете вытягивать элементы из списка.

И в случае с приведенным выше кодом ничто не вытягивает элементы из последовательности, поэтому ни одна из операций отображения напоследовательность будет происходить внутри блока runBlocking.

0 голосов
/ 25 ноября 2018

Это потому, что list.map - это inline fun, что может быть потому, что это энергичная операция, которая возвращает новый список.inline fun может допускать блок suspend, потому что он больше похож на макрос: он расширяется до места вызова.Пока сайт вызова находится в пределах блока suspend, это работает нормально. С другой стороны,

sequence.map является ленивым и просто добавляет еще одну лямбду в конвейер операций, которые будут выполнятьсяв конце концов, когда вы извлекаете элементы из последовательности.

Ближайшим эквивалентом ленивых последовательностей в мире приостановки является канал, но он меняет модель программирования.

...