Scala DISCUSSION

What does yield do in a Scala for comprehension, and why does it work on Option and Future too?

Started by amritlal Scala for comprehensionyieldmap and flatMapOption chainingFuture composition
4 replies 248 views 5 participants
Latest activity · 30 Sep 2026

What does yield do in a Scala for comprehension, and why does it work on Option and Future too?

amritlal Scala Forum
#1

I first read for (x <- xs) yield x * 2 as a loop that returns values, a bit like a Python generator. Then I found code such as for { user <- findUser(id); addr <- user.address } yield addr.city where nothing is a collection; both calls return Option. The same syntax is used with Future.

What is the for ... yield construct really, and what decides the type of the result?

Community replies 4

Re: What does yield do in a Scala for comprehension, and why does it work on Option and Future too?

#2

It is not a loop construct at all; it is syntax that the compiler rewrites into method calls. A single generator with yield becomes map: for (x <- xs) yield x * 2 is xs.map(x => x * 2). Every generator except the last becomes flatMap, an if guard becomes withFilter, and a for without yield becomes foreach.

So for { x <- List(1, 2, 3); y <- List(10, 20) } yield x * y is List(1, 2, 3).flatMap(x => List(10, 20).map(y => x * y)), which gives List(10, 20, 20, 40, 30, 60): six results, one for each combination.

Re: What does yield do in a Scala for comprehension, and why does it work on Option and Future too?

#3

Because the rewrite only needs those methods, any type that defines map and flatMap can be used. For Option, flatMap means "continue only if there is a value". Your example is findUser(id).flatMap(user => user.address.map(addr => addr.city)): if either step yields None, the whole result is None, with no null checks. for { a <- Some(2); b <- Some(3) } yield a + b is Some(5), and replacing either side with None gives None.

Either works the same way and stops at the first Left, which makes it convenient for validation steps that can each fail with an error message.

Re: What does yield do in a Scala for comprehension, and why does it work on Option and Future too?

#4

The result type follows the first generator, and all generators have to be compatible with it. Starting from a List gives a List; starting from a Set gives a Set, so duplicates vanish: for (x <- Set(1, 2, 3)) yield x % 2 has only two elements. You cannot put an Option first and a List second, because Option.flatMap expects a function that returns an Option; convert explicitly with .toList when you need to mix them.

Unlike a Python generator, nothing is lazy here unless the source is. A List is processed completely and a new list is built. Use an Iterator, a LazyList or .view if you want elements produced on demand.

Re: What does yield do in a Scala for comprehension, and why does it work on Option and Future too?

#5

With Future there is a well-known trap. In for { a <- loadA(); b <- loadB() } yield a + b, the call to loadB() sits inside the flatMap of the first future, so it starts only after loadA() has completed. If each takes 2 seconds, the total is about 4 seconds.

To run them concurrently, create both futures before the comprehension: val fa = loadA(); val fb = loadB() and then for { a <- fa; b <- fb } yield a + b. Both are already running, and the total is about 2 seconds. The comprehension only describes how to combine the results.

TEP COMMUNITY