You could optimize this example bit by using a withFilter call instead of filter. This would avoid the creation of an intermediate data structure for male persons:
scala> persons withFilter (p => !p.isMale) flatMap (p => (p.children map (c => (p.name, c.name))))
res1: List[(String, String)] = List((Julie,Lara), (Julie,Bob))
These queries do their job, but they are not exactly trivial to write or understand. Is there a simpler way? In fact, there is. Remember the for expressions in Section 7.3? Using a for expression, the same example can be written as follows:
scala> for (p <- persons; if !p.isMale; c <- p.children) yield (p.name, c.name)
res2: List[(String, String)] = List((Julie,Lara), (Julie,Bob))
The result of this expression is exactly the same as the result of the previous expression. What’s more, most readers of the code would likely find the for expression much clearer than the previous query, which used the higherorder functions, map, flatMap, and withFilter.
However, the last two queries are not as dissimilar as it might seem. In fact, it turns out that the Scala compiler will translate the second query into the first one. More generally, all for expressions that yield a result are translated by the compiler into combinations of invocations of the higher-order methods map, flatMap, and withFilter. All for loops without yield are translated into a smaller set of higher-order functions: just withFilter and foreach.
In this chapter, you’ll find out first about the precise rules of writing for expressions. After that, you’ll see how they can make combinatorial problems easier to solve. Finally, you’ll learn how for expressions are translated, and how as a result, for expressions can help you “grow” the Scala language into new application domains.
23.1 For expressions
Generally, a for expression is of the form:
Cover · Overview · Contents · Discuss · Suggest · Glossary · Index