# For-comprehension, a Scala language concept

Last updated

The for-comprehension is highly important syntatic enhancement in functional programming languages.

``````assert(List(1, 2, 3).map(num => num + 1) == List(2, 3, 4))
``````

Becomes:

``````assert((for (num <- List(1, 2, 3)) yield num + 1) == List(2, 3, 4))
``````

And

``````val Multiplier = 10

assert(
List(1, 2, 3)
.flatMap(num =>
List(num * Multiplier - 1, num * Multiplier, num * Multiplier + 1)
)
.map(num => num + 1) == List(10, 11, 12, 20, 21, 22, 30, 31, 32)
)
``````

Becomes:

``````val Multiplier = 10

val result: List[Int] = for {
num <- List(1, 2, 3)
anotherNum <-
List(num * Multiplier - 1, num * Multiplier, num * Multiplier + 1)
} yield anotherNum + 1

assert(result == List(10, 11, 12, 20, 21, 22, 30, 31, 32))
``````

Even more interestingly, an 'if' guard may be available for some container types, such as:

``````val Multiplier = 10

object Odd {
def unapply(num: Int): Option[Int] = Option.when(num % 2 == 1)(num)
}

val result: List[Int] = for {
Odd(num) <- List(1, 2, 3) if num > 2
anotherNum <-
List(num * Multiplier - 1, num * Multiplier, num * Multiplier + 1)
} yield anotherNum + 1

assert(result == List(30, 31, 32))
``````

Interestingly, this applies to pattern matching as well, which you can do inside for-comprehensions!

## Background

Prior to Scala and F#, for-comprehensions were widely used in Haskell and XQuery. The key selling point is how much more concise they can make the code. There are numerous definitions of what they do (such as being 'a way to compose Monads'), However the most-straightforward way to see them is as something that lets you combine sequences of .map and .flatMap, as well as .collect/.withFilter in a very straight-forward way.

This can include the IO type of cats-effect, as well as simple types like Option Type and other container types like Lazy List or View.

What is cool in Scala is that often Option types can be combined with Iterables, allowing for very terse syntax.

for-comprehensions are in particular useful where code becomes unreadable due to a large number of chains of .map and .flatMap - and you just want to have everything in one column. This anti-pattern of unreadable chains of code is also known as callback hell (example).

Various names are given for for-comprehensions in different languages: do-notation in Haskell, await-async in JavaScript, list comprehensions in F#, generators in Python. Even SQL queries can be considered a form of for-comprehensions.

# Scala Algorithms: The most comprehensive library of algorithms in standard pure-functional Scala

## How our 100 algorithms look

1. A description/goal of the algorithm.
2. An explanation with both Scala and logical parts.
3. A proof or a derivation, where appropriate.
4. Links to Scala concepts used in this specific algorithm, also unit-tested.
5. An implementation in pure-functional immutable Scala, with efficiency in mind (for most algorithms, this is for paid subscribers only).
6. Unit tests, with a button to run them immediately in our in-browser IDE.

### Study our 100 Scala Algorithms: 6 fully free, 100 published & 0 upcoming

Fully unit-tested, with explanations and relevant concepts; new algorithms published about once a week.

### Explore the 22 most useful Scala concepts

To save you going through various tutorials, we cherry-picked the most useful Scala concepts in a consistent form.

## Subscribe to Scala Algorithms

Maximize your Scala with disciplined and consistently unit-tested solutions to 100+ algorithms.

Use it from improving your day-to-day data structures and Scala; all the way to interviewing.