当我第一次开始关注Scala时,我喜欢看起来很容易理解。它们似乎有点像我从Java 5习惯的foreach循环,但功能限制和很多甜美的句法友好。
但是当我吸收了Scala风格时,我发现每次我使用for-comprension时我都会使用map
,flatMap
,filter
,{{1而是{}和} reduce
。代码的意图对我来说似乎更清晰,潜在的隐藏意外更少,而且它们通常也是更短的代码。
据我所知,无论如何,for-comprehension总是编译成这些方法,所以我想知道:它们实际上是为了什么?我错过了一些功能性的复兴(这不是第一次)?为了理解做其他功能不能做的事情,或者至少会笨拙地做些什么?他们是否根据特定用例发光?这真的只是个人品味的问题吗?
答案 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过渡,可能包含了理解。无论如何,选择的是风格和偏好。