Scala 的 for 推导式:重要特征还是语法糖?
当我第一次开始研究 Scala 时,我喜欢 for 推导式的外观。它们似乎有点像我在 Java 5 中习惯的 foreach 循环,但有功能限制和很多漂亮的语法。
但当我吸收了 Scala 风格后,我发现每次我可以使用 for 压缩时,我都会使用 map
、flatMap
、filter、
reduce
和 foreach
来代替。这样,代码的意图对我来说似乎更清晰,潜在的隐藏惊喜更少,而且它们通常也更短的代码。
据我所知,for 理解总是被编译成这些方法,所以我想知道:它们实际上是用来做什么的?我是否错过了一些功能性的重新评估(这不是第一次)? for 理解是否可以做其他功能不能做的事情,或者至少会笨拙得多?它们在特定用例下表现出色吗?这真的只是个人品味问题吗?
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.
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
, reduce
and foreach
instead. The intention of the code seems clearer to me that way, with fewer potential hidden surprises, and they're usually shorter code too.
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
请参阅此问题。简而言之,for 推导式可以更具可读性。特别是,如果您有许多嵌套生成器,则您所做的实际范围会变得更加清晰,并且不需要巨大的缩进。
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 理解的另一个重要用途是用于内部 DSL。 ScalaQL 就是一个很好的例子。它可以把这个变成
这个
,甚至更多。
Another great use of for-comprehension is for internal DSL. ScalaQL is a great example of this. It can turn this
into this
and a whole lot more.
for 推导式是语法糖,但这并不意味着它们不重要。它们通常比扩展形式更简洁,这很好,但也许更重要的是它们帮助命令式语言的程序员使用函数式构造。
当我第一次开始使用 Scala 时,我经常使用 for 推导式,因为它们很熟悉。然后我几乎完全停止了,因为我觉得使用底层方法更明确,因此更清晰。现在我又回到使用 for 理解,因为我认为它们更好地表达了我正在做的事情的意图,而不是做事的手段。
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.
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.
在某些情况下,推导式可以更好地表达意图,因此当它们这样做时,请使用它们。
另请注意,使用 for 推导式,您可以免费获得模式匹配。例如,使用 for 理解式迭代 Map 比使用
简单得多:
for ((key, value) <- map) println (key + "-->" + value)
:foreach
map foreach { case (key, value) =>; println(键+“-->”+值)}
In some cases, for comprehensions can express intent better, so when they do, use them.
Also note that with for comprehensions, you get pattern matching for free. For example, iterating over a Map is much simpler with for comprehension:
for ((key, value) <- map) println (key + "-->" + value)
than with foreach:
map foreach { case (key, value) => println (key + "-->" + value) }
你是对的。 for 理解是语法糖。我相信一旦你习惯了它们,底层的方法就会更简洁、更容易阅读。
比较以下等效语句:
在我看来,#1 中添加分号分散了人们对这是一个单链语句的感觉。还有一种感觉是 i 是一个 var(是 1,还是 99,还是介于两者之间的值?),这有损于其他函数式风格。
选项 2 显然是对对象的一系列方法调用。链条中的每个环节都明确说明其责任。没有中间变量。
也许包含推导式是为了方便开发人员从 Java 过渡。无论如何,选择哪一个取决于风格和偏好。
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.
Compare the following equivalent statements:
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.
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.
Perhaps for comprehensions are included as a convenience for developers transitioning from Java. Regardless, which is chosen is a matter of style and preference.