Scala 中的 for 表达式与 foreach

发布于 2024-10-08 04:47:27 字数 618 浏览 0 评论 0原文

我正在通过 Scala 编程,尽管我很想从 Python 的角度看待事物,我不想编写“Python in Scala”。

我不太确定就控制流而言该怎么做:在 Python 中,我们使用 for x in some_iterable 到死,而且我们喜欢它。 Scala 中存在一个非常相似的构造,Odersky 将其称为 for 表达式,可能是为了将其与 Java for 循环区分开来。另外,Scala 对于可迭代数据类型有一个 foreach 属性(我猜它是一个属性,我对 Scala 的了解不够,无法正确命名它)。不过,似乎我不能使用 foreach 做更多事情,而只是为容器中的每一项调用一个函数。

这给我留下了几个问题。首先,Scala 中的 for 表达式是重要/频繁使用的结构,就像在 Python 中一样;其次,我什么时候应该使用 foreach 而不是 for 表达式(除了在每个函数上调用函数的明显情况之外)容器中的物品)?

我希望我没有太含糊或过于宽泛,但我只是想了解 Scala 中的一些设计/语言基础知识(到目前为止看起来很酷)。

I'm working my way through Programming in Scala, and though I'm tempted to look at things from the perspective of Python, I don't want to program "Python in Scala."

I'm not quite sure what to do as far as control flow goes: in Python, we use for x in some_iterable to death, and we love it. A very similar construct exists in Scala which Odersky calls a for expression, probably to distinguish it from the Java for loop. Also, Scala has a foreach attribute (I guess it would be an attribute, I don't know enough about Scala to name it correctly) for iterable data types. It doesn't seem like I can use foreach to do much more than call one function for each item in the container, though.

This leaves me with a few questions. First, are for expressions important/heavily used constructs in Scala like they are in Python, and second, when should I use foreach instead of a for expression (other than the obvious case of calling a function on each item of a container)?

I hope I'm not being terribly ambiguous or overbroad, but I'm just trying to grok some of the design/language fundamentals in Scala (which seems very cool so far).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

风为裳 2024-10-15 04:47:27

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 =>第 1 代。如果没有匹配,则迭代中将忽略这些元素。

scala> val list = List(Some(1), None, Some(2))
scala> for (Some(i) <- list) yield i
res2: List[Int] = List(1, 2)

我认为 for 在该语言中占有重要地位。我可以从你正在阅读的书中有一整章(23)来介绍它!

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!

拿命拼未来 2024-10-15 04:47:27

是的,Scala 推导式(众所周知)被大量使用,但它们实际上只是特定方法组合的语法糖,许多人更喜欢直接调用这些方法而不是使用语法糖。

为了更好地理解 Scala 的理解,请参阅此问题。特别是,您会看到 for (x <- xs) f(x)xs.foreach(x => f(x)) 相同代码>.

现在,您提到您似乎不太使用 foreach 方法,但我要指出的是,几乎所有 Scala 集合的方法都是(或可以)仅使用 实现的foreach。请参阅 Traversable 的文档 - 它的所有方法都可以仅使用 foreach 来实现。

请注意,Scala 的 yield 与 Python 的 yield 没有相似之处 - 您可以查找这个问题也是如此。

Yes, Scala for comprehensions (as they are commonly known) are used a lot, but they are really just syntactic sugar for a particular combination of methods, and many prefer to call these methods directly instead of using the syntactic sugar.

To better understand Scala for comprehensions, please refer to this question. In particular, you'll see that for (x <- xs) f(x) is the same thing as xs.foreach(x => f(x)).

Now, you mention that you don't seem much use with foreach method, but I'll point out that almost all of the methods of Scala collections are (or can be) implemented with just foreach. See the documentation for Traversable -- all of its methods can be implemented with only foreach.

Note that Scala's yield bears no resemblance to Python's yield -- you can look up that question too.

苹果你个爱泡泡 2024-10-15 04:47:27

凭借对嵌套迭代、过滤器和转换的支持,我认为 Scala 的 for 是该语言的强项之一,并且非常核心。与使用 foreachmapfilter 相比,我更倾向于使用它。

With its support for nested iteration, filters, and transformation, I'd say Scala's for is one of the strong points of the language and very central. I tend to favor it over using foreach, map and filter.

遗心遗梦遗幸福 2024-10-15 04:47:27

foreach 是函数式风格,而 for 是命令式风格。如果您曾经使用过 lisp 或方案,那么您已经熟悉函数式编程。如果你还没有,那么一开始可能会有点混乱。我要做的第一件事是阅读闭包语法,这些语法是传递给 foreach 之类的匿名函数。一旦你明白了,一切都会变得更有意义。

The foreach is a functional style while the for is an imperative style. If you've ever done any lisp or scheme, you're already familiar with functional programming. If you haven't then it might be a bit confusing at first. The first thing I would do is read up on the closure syntax which are anonymous functions you pass into things like foreach. Once you understand that it will all make more sense.

染火枫林 2024-10-15 04:47:27

您的问题主要通过以下内容得到解答:

Scala 的 For Compressives

Scala Yield

总结一下:它很大程度上是风格上的。就我个人而言,我喜欢函数式方法,但更喜欢处理嵌套循环时推导式的简洁性。

Your questions are largely answered by the following:

Scala's For Comprehensions

Scala Yield

To summaraize: It's largely stylistic. Personally, I favor the functional methodology, but prefer the succinctness of comprehensions when dealing with nested loops.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文