Нет, это не включает параллелизм
for
Понимание только поможет вам опустить несколько скобок и отступов.
Код, который вы указали, переводите [flat]map
строго эквивалентно:
async.boundedQueue[Stuff](100).flatMap{ a =>
val d = computeB(a).flatMap{
b => computeD(b).map{ result =>
result
}
}
val f = computeC(a).flatMap{ c =>
computeE(c).flatMap{ e =>
computeF(e).map{ result =>
result
}
}
}
d.merge(f).map(g => g)
}
Видите, это поможет вам опустить несколько скобок и отступов (шутка)
Параллельность скрыта в flatMap
и map
Как только вы поймете, как for
переводится в flatMap
и map
, вы можете реализовать свой параллелизм внутри них.
Поскольку map
принимает функцию в качестве аргумента, это не означает, что функция выполняется во время выполнения функции map
, вы можете перенести функцию на другой поток или запустить ее последним. Вот как реализован параллелизм.
Взять Promise
и Future
как пример:
val future: Future = ```some promise```
val r: Future = for (v <- future) yield doSomething(v)
// or
val r: Future = future.map(v => doSomething(v))
r.wait
Функция doSomething
не выполняется во время выполнения функции Future.map
, вместо этого она вызывается при фиксации promise
.
Заключение
Как реализовать параллелизм с использованием синтаксиса for
:
for
преобразуется в flatMap
и map
компилятором scala
- Напишите вам
flatMap
и map
, где вы получите функцию обратного вызова из аргумента
- Вызывайте функцию, которую вы получили, когда и где хотите
Дальнейшее чтение
Функция управления потоком во многих языках имеет одно и то же свойство, они похожи на продолжение с разделителями shift/reset
, где они фиксируют следующее выполнение до области видимости в функцию.
JavaScript:
async function() {
...
val yielded = await new Promise((resolve) => shift(resolve))
// resolve will captured execution of following statements upto end of the function.
...captured
}
Haskell:
do {
...
yielded_monad <- ```some monad``` -- shift function is >>= of the monad
...captured
}
Scala:
for {
...
yielded_monad <- ```some monad``` // shift function is flatMap/map of the monad
...captured
} yield ...
в следующий раз, когда вы увидите языковую функцию, которая фиксирует выполнение после выполнения функции, вы знаете, что можете реализовать управление потоком с помощью этой функции.
Разница между продолжением с разделителями и call / cc заключается в том, что call / cc захватывает все последующее выполнение программы, но продолжение с разделителями имеет область действия.