Scala 的 for-comprehensions:重要特征还是语法糖?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1385931/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Scala's for-comprehensions: vital feature or syntactic sugar?
提问by Marcus Downing
When I first started looking at Scala, I liked the look of for-comprehensions. They seemed to be a bit like the foreach loops I was used to from Java 5, but with functional restrictions and a lot of sweet syntactic niceness.
当我第一次开始研究 Scala 时,我喜欢 for-comprehensions 的外观。它们似乎有点像我在 Java 5 中习惯使用的 foreach 循环,但有功能限制和许多甜蜜的句法优点。
But as I've absorbed the Scala style, I find that every time I could use a for-comprension I'm using map, flatMap, filter, reduceand foreachinstead. The intention of the code seems clearer to me that way, with fewer potential hidden surprises, and they're usually shorter code too.
但是随着我吸收了 Scala 风格,我发现每次我可以使用 for-comprension 时,我都使用map, flatMap, filter, reduceandforeach来代替。通过这种方式,代码的意图对我来说似乎更清晰,潜在的隐藏惊喜更少,而且它们通常也是更短的代码。
As far as I'm aware, for-comprehensions are always compiled down into these methods anyway, so I'm wondering: what are they actually for? Am I missing some functional revalation (it wouldn't be the first time)? Do for-comprehensions do something the other features can't, or would at least be much clumsier at? Do they shine under a particular use case? Is it really just a matter of personal taste?
据我所知,无论如何,for-comprehensions 总是被编译成这些方法,所以我想知道:它们实际上是做什么用的?我是否错过了一些功能重估(这不是第一次)?for-comprehensions 做其他功能不能做的事情,或者至少会笨拙得多?它们是否在特定用例下闪耀?这真的只是个人品味的问题吗?
采纳答案by Daniel C. Sobral
Please refer to this question. The short answer is that for-comprehensions can be more readable. In particular, if you have many nested generators, the actual scope of what you are doing becomes more clear, and you don't need huge indents.
请参考这个问题。简短的回答是 for-comprehensions 可以更具可读性。特别是,如果你有很多嵌套的生成器,你所做的实际范围就会变得更加清晰,而且你不需要巨大的缩进。
回答by Walter Chang
Another great use of for-comprehension is for internal DSL. ScalaQLis a great example of this. It can turn this
for-comprehension 的另一个重要用途是用于内部 DSL。 ScalaQL就是一个很好的例子。可以转这个
val underAge = for {
p <- Person
c <- Company
if p.company is c
if p.age < 14
} yield p
into this
进入这个
SELECT p.* FROM people p JOIN companies c ON p.company_id = c.id WHERE p.age < 14
and a whole lot more.
还有更多。
回答by Erik Engbrecht
for-comprehensions are syntactic sugar, but that doesn't mean they aren't vital. They are usually more concise than their expanded form, which is nice, but perhaps more importantly they help programmers from imperative languages use functional constructs.
for-comprehensions 是语法糖,但这并不意味着它们不重要。它们通常比它们的扩展形式更简洁,这很好,但也许更重要的是它们帮助命令式语言的程序员使用函数式构造。
When I first started with Scala I used for-comprehensions a lot, because they were familiar. Then I almost stopped completely, because I felt like using the underlying methods was more explicit and therefore clearer. Now I'm back to using for-comprehensions because I think they better express the intent of what I'm doing rather than the means of doing it.
当我第一次开始使用 Scala 时,我经常使用 for-comprehensions,因为它们很熟悉。然后我几乎完全停止了,因为我觉得使用底层方法更明确,因此更清晰。现在我又回到使用 for-comprehensions 了,因为我认为它们更好地表达了我正在做的事情的意图,而不是做这件事的方式。
回答by thSoft
In some cases, for comprehensions can express intent better, so when they do, use them.
在某些情况下,因为理解可以更好地表达意图,所以当它们这样做时,请使用它们。
Also note that with for comprehensions, you get pattern matchingfor free. For example, iterating over a Map is much simpler with for comprehension:
另请注意,对于理解,您可以免费获得模式匹配。例如,为了理解,遍历 Map 就简单得多:
for ((key, value) <- map) println (key + "-->" + value)
for ((key, value) <- map) println (key + "-->" + value)
than with foreach:
与 foreach 相比:
map foreach { case (key, value) => println (key + "-->" + value) }
map foreach { case (key, value) => println (key + "-->" + value) }
回答by Synesso
You are right. The for-comprehension is syntactic sugar. I believe the underlying methods are more succinct and easier to read, once you are used to them.
你说的对。for-comprehension 是语法糖。我相信,一旦你习惯了底层的方法,它们就会更加简洁易读。
Compare the following equivalent statements:
比较以下等效语句:
1. for (i <- 1 to 100; if (i % 3 == 0)) yield Math.pow(i, 2)
2. (1 to 100).filter(_ % 3 == 0).map(Math.pow(_, 2))
In my opinion, the addition of the semicolon in #1 distracts from the sense that this is a single chained statement. There is also a sense that i is a var (is it 1, or is it 99, or something inbetween?) which detracts from an otherwise functional style.
在我看来,在#1 中添加分号分散了人们对这是一个单链语句的看法。还有一种感觉是 i 是一个 var(它是 1,还是 99,或者介于两者之间?),这有损于其他功能风格。
Option 2 is more evidently a chain of method calls on objects. Each link in the chain clearly stating its responsibility. There are no intermediate variables.
选项 2 更明显地是对对象的一系列方法调用。链条中的每个环节都清楚地说明了其责任。没有中间变量。
Perhaps for comprehensions are included as a convenience for developers transitioning from Java. Regardless, which is chosen is a matter of style and preference.
也许是为了方便从 Java 过渡的开发人员。无论如何,选择哪个是风格和偏好的问题。

