Scala:ForComprehension是一种功能性方法还是命令式的?

时间:2015-10-07 15:50:59

标签: scala

我的收藏品:

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循环是否来自命令式?

1 个答案:

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

目前尚不清楚这里发生了什么。但是,由于我们已定义mapflatMap,我们可以   使用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指定在语句边界发生的内容