Skip to main content

for comprehension

If a type has flatMap and map (or it has flatMap and map as its extension methods), you can use for comprehension instead of using nested flatMaps and map.

flatMap and map​

In for comprehension, <-s (left arrows) are flatMap except for the last one. The last <- is map.

for {
b <- foo(a)
c <- bar(b)
d <- baz(c)
} yield b + c + d + e

is equivalent to

foo(a).flatMap { b =>
bar(b).flatMap { c =>
baz(c).map { d =>
b + c + d + e
}
}
}

So

for {
b <- foo(a) // flatMap { b =>
c <- bar(b) // flatMap { c =>
d <- baz(c) // map { d =>
} yield b + c + d + e

for {
b <- foo(a)
c <- bar(b)
} yield b + c + d

is equivalent to

foo(a).flatMap { b =>
bar(b).map { c =>
b + c + d
}
}

So

for {
b <- foo(a) // fatMap { b =>
c <- bar(b) // map { c =>
} yield b + c + d

for {
b <- foo(a)
} yield b + c

is equivalent to

foo(a).map { b =>
b + c
}

So

for {
b <- foo(a) // map { b =>
} yield b + c

It means the following one is meaningless

for {
b <- foo(a)
} yield b

because it's equivalent to

foo(a).map { b =>
b
}

which does nothing.

So you can simply do this instead.

foo(a)

A single <- in for-comprehension could be flapMap as well depending on the return type of the function.

for {
b <- foo(a)
} yield bar(b)

where bar(b) returns the same type as foo(a)'s.

It is equivalent to

foo(a).flatMap { b =>
bar(b)
}

So

for {
b <- foo(a) // foo(a).flatMap { b =>
} yield bar(b)

If your for-comprehension has only one <-, you can simply use map or flatMap instead of for-comprehension, as it doesn't add much readability for a single map or flatMap case.