我的收藏品:
val l1 = List(1, 2, 3)
val l2 = List("A", "B", "C")
这是一种必要的方法:
for {
e1 <- l1
e2 <- l2
} {
println(s"$e1 - $e2")
}
和FP方法:
l1 foreach {
a => l2 foreach {
b => println {
s"$a - $b"
}
}
}
然而,经典的for
循环代表了纯粹的命令式风格,我对For Comprehension
循环的强制性有一些疑问。所以我的问题是:我是对的,For Comprehension
循环是否来自命令式?
答案 0 :(得分:3)
for-comprehension是一种功能性的写作方式&#34;命令式的&#34;代码。
我引用来自&#34; Scala中的功能编程&#34;中的Paul Chiusano和Runar Bjarnason。因为我永远无法把它变得更好:
Page 89
不是命令式和函数式编程的对立面吗?
绝对不是。请记住,函数式编程只是编程而没有 副作用。命令式编程是关于使用语句进行编程的 修改一些程序状态,正如我们所见,维护是完全合理的 没有副作用的状态。
函数式编程对编写命令式程序有很好的支持 这些程序可以在等等方面进行推理的额外好处是因为 他们的参考是透明的。
来自同一页面的示例:
val ns: Rand[List[Int]] =
int.flatMap(x =>
int.flatMap(y =>
ints(x).map(xs =>
xs.map(_ % y))))
目前尚不清楚这里发生了什么。但是,由于我们已定义
map
和flatMap
,我们可以 使用for-understanding来恢复命令式风格:
val ns: Rand[List[Int]] = for {
x <- int
y <- int
xs <- ints(x)
} yield xs.map(_ % y)
这段代码更容易阅读(和写入),它看起来像是必须的 保持某种状态的程序。但它是相同的代码。我们得到了下一个
Int
和 将其分配给x
,然后获取下一个Int
并将其分配给y
,然后生成一个长度列表x
,最后以模y
的形式返回包含所有元素的列表。 通过理解来促进这种命令式编程(或flatMaps
),我们真的只需要两个原始状态组合器 - 一个用于读取 国家和一个写国家。
第203页的另外一篇:
我们可以看到一连串的
flatMap
来电(或等价的 for-comprehension)就像一个命令式程序,带有赋值给变量的语句, 和 monad指定在语句边界发生的内容。