python uses for in list comprehensions and generator expressions. Those are very similar to the scala for expression:
this is python
>>> letters = ['a', 'b', 'c', 'd']
>>> ints = [0, 1, 2, 3]
>>> [l + str(i) for l in letters for i in ints if i % 2 == 0]
['a0', 'a2', 'b0', 'b2', 'c0', 'c2', 'd0', 'd2']
this is scala
scala> val letters = List('a', 'b', 'c', 'd')
scala> val ints = List(0, 1, 2, 3)
scala> for (l <- letters; i <- ints if i % 2 == 0) yield l.toString + i
res0: List[java.lang.String] = List(a0, a2, b0, b2, c0, c2, d0, d2)
Each construct can take a number of generators/iterators, apply filters expressions and yield a combined expression. In python the (expr for v1 in gen1 if expr1 for v2 in gen2 if expr2) is roughly equivalent to:
for v1 in gen1:
if expr1:
for v2 in gen2:
if expr2:
yield expr
In scala for (v1 <- gen1 if expr1; v2 <- gen2 if expr2) yield expr is roughly equivalent to:
gen1.withFilter(expr1).flatMap(v1 => gen2.withFilter(expr2).map(v2 => expr))
If you love the python for x in xs syntax, you’ll likely love the scala for expression.
Scala has some additional syntax and translation twists. Syntax wise for can be used with braces so that you can put statements on separate lines. You can also perform value assignments.
val res = for {
i <- 1 to 20; i2 = i*i
j <- 1 to 20; j2 = j*j
k <- 1 to 20; k2 = k*k
if i2 + j2 == k2
} yield (i, j, k)
Also v1 <- gen1 really performs a match case v1 => gen1. If there is no match those elements are ignored from the iteration.
scala> val list = List(Some(1), None, Some(2))
scala> for (Some(i) <- list) yield i
res2: List[Int] = List(1, 2)
I think for has an important place in the language. I can tell from the fact there is a whole chapter (23) about it in the book you’re reading!