expression式与foreach在斯卡拉
我正在通过Scala中的编程工作,虽然我很想从Python的angular度来看待事物,但是我不想编写“Scala中的Python”。
就控制stream程而言,我不太确定该怎么做:在Python中,我们使用for x in some_iterable
去死,我们喜欢它。 在Odersky调用for expression式的 Scala中存在一个非常类似的构造,可能将它与Java for循环区分开来。 另外,对于可迭代数据types,Scala还有一个foreach
属性(我想这将是一个属性,我不太了解Scala的名称)。 不过,似乎我不能使用foreach
来为容器中的每个项目调用一个函数。
这让我有几个问题。 首先,对于在Scala中重要/重要的expression式,就像它们在Python中一样,第二,何时应该使用foreach
而不是forexpression式(除了在容器的每个项目上调用函数的明显情况)?
我希望自己不是非常模棱两可,但是我只是想在Scala中devise一些devise/语言基础知识(目前看起来非常酷)。
python for
列表parsing和生成器expression式。 这些与expression式的scala 很相似:
这是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)
每个构造都可以使用多个生成器/迭代器,应用filterexpression式并生成组合expression式。 在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
在for (v1 <- gen1 if expr1; v2 <- 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))
如果你喜欢for x in xs
语法的python,你可能会喜欢用scala for
expression。
斯卡拉有一些额外的语法和翻译曲折。 语法wise 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)
我觉得在语言中有一个重要的地方。 我可以从这个事实中看出,你正在阅读的书里有一整章(23)
是的,斯卡拉理解(因为他们是众所周知的)被使用了很多,但他们真的只是一个特定的方法组合语法糖,许多人喜欢直接调用这些方法,而不是使用语法糖。
为了更好地理解Scala的理解,请参考这个问题 。 特别是,你会看到for (x <- xs) f(x)
和xs.foreach(x => f(x))
。
现在,你提到你用foreach
方法似乎没什么用处,但是我会指出几乎所有的Scala集合的方法都是(或者可以)用foreach
来实现的。 请参阅Traversable
的文档 – 所有的方法只能用foreach
实现。
请注意,Scala的yield
与Python的yield
没有任何相似之处 – 你也可以查看这个问题。
通过对嵌套迭代,过滤和转换的支持,我认为Scala是语言的优势之一,也是非常重要的。 我倾向于使用foreach
, map
和filter
来支持它。
foreach是一种function性的风格,而for是一种势在必行的风格。 如果你曾经做过任何口头或计划,那么你已经熟悉函数式编程。 如果你还没有,那么起初可能有点混乱。 我要做的第一件事是读闭包语法,这些匿名函数是你传入foreach之类的东西。 一旦你明白这将是更有意义的。
你的问题在很大程度上回答如下:
斯卡拉的理解
斯卡拉收益率
总结:这在很大程度上是文体上的。 就个人而言,我赞成function方法论,但在处理嵌套循环时,更喜欢理解的简洁性。