Python 在列表推导和生成器表达式中使用 for
。这些与 Scala 中的 for
表达式非常相似:
这是 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']
这是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)
每个构造器都可以接受多个生成器/迭代器,应用过滤表达式并产生一个组合表达式。在Python中,(expr for v1 in gen1 if expr1 for v2 in gen2 if expr2)
大致相当于:
for v1 in gen1:
if expr1:
for v2 in gen2:
if expr2:
yield expr
在Scala中,for (v1 <- gen1 if expr1; v2 <- gen2 if expr2) yield expr
大致等同于:
gen1.withFilter(expr1).flatMap(v1 => gen2.withFilter(expr2).map(v2 => expr))
如果您喜欢Python的for x in xs
语法,那么您可能会喜欢Scala中的for
表达式。
Scala具有一些额外的语法和转换技巧。从语法角度讲,可以使用花括号将for
与语句放在不同的行上。您还可以执行值分配操作。
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)
此外,v1 <- gen1
实际上执行了一个匹配 case v1 => gen1
。如果没有匹配,这些元素将从迭代中被忽略。
scala> val list = List(Some(1), None, Some(2))
scala> for (Some(i) <- list) yield i
res2: List[Int] = List(1, 2)
我认为for
在编程语言中有重要的地位。你正在阅读的书中甚至有一个完整的第23章节专门讲解它!