Прочитав этот статья и понял, что примерно все функции после ключевого слова yield являются функцией map. Хотя все операторы в for являются функциями flatMap. Почему это так? Почему функция после yield может быть функцией flatMap, а также функции в for могут быть функциями map?
Предлагаю сначала прочитать docs.scala-lang.org/tour/for-comprehensions.html
Ваше утверждение неверно. Последний генератор, <-, внутри for (перед yield) транслируется в вызов map(). Генераторы до (см. Выше) последнего генератора транслируются в вызовы flatMap().





Ваш первый пункт примерно верен. Заявление
for (x <- list) yield f(x)
Эквивалентно
list.map(x => f(x))
Но вы не совсем правы относительно того, как используется flatMap, когда существует более одного списка.
Вызов flatMap используется, если вы хотите одновременно перебирать другой список:
for (
x <- list1
y <- list2
) yield f(x, y)
Это эквивалентно
list1.flatMap(x => list2.map(y => f(x, y)))
Вызов map заключен в вызов flatMap, поэтому в результате получается простой список. Если бы внешний вызов был map, то результатом был бы вложенный список.
Внутренний вызов - это всегда вызов map, все внешние вызовы - это flatMap. Так
for (
x <- list1
y <- list2
z <- list3
) yield f(x, y, z)
Является
list1.flatMap(x => list2.flatMap(y => list3.map(z => f(x, y, z))))
В конце концов, лучшее, что можно сделать с for, - это поэкспериментировать с ним, пока он не сделает то, что вы хотите, и через некоторое время он станет интуитивно понятным.
Ибо понимание - это просто синтаксический сахар. Он очищает от сахара в плоскую карту, отображает и фильтрует в соответствии с правилами. Ответ на ваше «почему»: «потому что так говорят правила».