斯卡拉的理解:重要特征还是语法糖?

时间:2009-09-06 15:32:06

标签: scala list-comprehension

当我第一次开始关注Scala时,我喜欢看起来很容易理解。它们似乎有点像我从Java 5习惯的foreach循环,但功能限制和很多甜美的句法友好。

但是当我吸收了Scala风格时,我发现每次我使用for-comprension时我都会使用mapflatMapfilter,{{1而是{}和} reduce。代码的意图对我来说似乎更清晰,潜在的隐藏意外更少,而且它们通常也是更短的代码。

据我所知,无论如何,for-comprehension总是编译成这些方法,所以我想知道:它们实际上是为了什么?我错过了一些功能性的复兴(这不是第一次)?为了理解做其他功能不能做的事情,或者至少会笨拙地做些什么?他们是否根据特定用例发光?这真的只是个人品味的问题吗?

5 个答案:

答案 0 :(得分:14)

请参阅this question。简短的回答是,理解可以更具可读性。特别是,如果你有许多嵌套的生成器,你所做的实际范围变得更加清晰,并且你不需要大的缩进。

答案 1 :(得分:11)

理解的另一个重要用途是内部DSL。 ScalaQL就是一个很好的例子。它可以改变这个

val underAge = for { 
  p <- Person 
  c <- Company 
  if p.company is c 
  if p.age < 14 
} yield p 

进入这个

SELECT p.* FROM people p JOIN companies c ON p.company_id = c.id WHERE p.age < 14 

还有更多。

答案 2 :(得分:10)

理解是语法糖,但这并不意味着它们不重要。它们通常比它们的扩展形式更简洁,这很好,但更重要的是它们可以帮助命令式语言的程序员使用功能结构。

当我第一次开始使用Scala时,我使用了很多理解,因为他们很熟悉。然后我几乎完全停止了,因为我觉得使用底层方法更明确,因此更清晰。现在我又回到了使用for -reherehension,因为我认为他们更好地表达了我正在做的事情的意图,而不是表达我的意图。

答案 3 :(得分:5)

在某些情况下,理解可以更好地表达意图,所以当他们这样做时,使用它们。

另请注意,对于理解,您可以免费获得模式匹配。例如,迭代Map可以更简单地理解:

for ((key, value) <- map) println (key + "-->" + value)

比foreach:

map foreach { case (key, value) => println (key + "-->" + value) }

答案 4 :(得分:3)

你是对的。理解是语法糖。一旦你习惯了它们,我相信基础方法更简洁,更容易阅读。

比较以下等效陈述:

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))

在我看来,在#1中添加分号会分散注意力,因为这是一个单链式语句。还有一种感觉,我是一个var(它是1,或者它是99,还是介于两者之间的东西?),这会减损其他功能风格。

选项2显然是对象的方法调用链。链中的每个环节都清楚地说明了它的责任。没有中间变量。

为了方便开发人员从Java过渡,可能包含了理解。无论如何,选择的是风格和偏好。