在Scala中,表达式和foreach的比较。

11 浏览
0 Comments

在Scala中,表达式和foreach的比较。

我正在阅读Scala编程指南,尽管我很想从Python的角度去看问题,但我不想用Scala来写“Python代码”。

在控制流方面,我还不太确定该怎么做:在Python中,我们会“致死地”使用for x in some_iterable来循环,我们非常喜欢它。Scala中也有一个非常相似的构造,Odersky称之为“for表达式”,可能是为了将其与Java的for循环区分开来。另外,Scala还有一个foreach属性(我想它可能是一个属性,但我对Scala了解不够深,不能正确命名它),用于迭代数据类型。不过,看起来我不能用foreach来做更多事情,除了对容器中的每个元素调用一个函数。

这让我有几个问题。首先,像在Python中一样,for表达式在Scala中是否重要/广泛使用?其次,除了在容器的每个元素上调用一个函数的明显情况之外,我应该在何时使用foreach而不是for表达式?

我希望我没有太不明确或过于广泛,但我只是试图理解Scala中的一些设计/语言基础知识(目前看起来非常酷)。

admin 更改状态以发布 2023年5月21日
0
0 Comments

是的,Scala的for comprehensions(如它们通常被称为)经常被使用,但它们其实只是一种特定方法组合的语法糖,很多人更喜欢直接使用这些方法而不是使用语法糖。

为了更好地理解Scala的for comprehensions,请参见这个问题。特别是,你会看到for (x<- xs) f(x)xs.foreach(x => f(x))是完全相同的。

现在,你提到你不太熟悉foreach方法的使用,但我要指出Scala集合的几乎所有方法都可以(或可以)只用foreach来实现。请查看Traversable的文档--它的所有方法都可以只用foreach来实现。

请注意,Scala的yield与Python的yield没有任何相似之处--你也可以查看那个问题。

0
0 Comments

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章)关于它,我可以看出这一点!

0