功能编程和命令式编程之间的妥协

时间:2014-06-06 16:05:12

标签: functional-programming immutability

我一直在使用函数式编程(FP)风格超过一年,我可以看到它的优点。但是,在某些情况下,命令式(可变状态,依赖于顺序的语句)更适合该问题,并且不会干扰FP的优点。我想知道我将在下面描述的妥协是否被广泛使用,如果它有一个名称,并且是否有任何语言或库有助于强制执行它(类似于Haskell强制执行纯FP的方式)。

我认为问题是更适合StackOverflow,但如果社区认为它应该转移到programmers.stackexchange,我会把它移到那里。

程序的两个方面可以是不可变的:符号绑定和数据结构。如果在Java中声明为“final”或在Scala中声明为“val”,则符号绑定是不可变的,如果没有可以就地更改它们的公共方法或函数,则数据结构是不可变的。这有四种情况:

  1. 不可变符号绑定,不可变数据结构(完整FP)
  2. 不可变符号绑定,可变数据结构(如Java中的“final HashMap x”)
  3. 可变符号绑定,不可变数据结构(如“Scala中的var x:immutable.Map”)
  4. 可变符号绑定,可变数据结构(完全命令)
  5. 不可变数据结构很有价值,因为它们不必被防御性复制并且可以利用结构共享,所以我只考虑#1和#3。可变符号绑定可能是令人困惑的依赖项的来源,但前提是它们在代码库的大部分内容共享。如果它们只在函数中作为局部变量(因此也是线程局部变量)可用,则它们是无害的。

    此外,在小规模上使用可变符号绑定非常有用 - 迭代数学算法对我来说是一个常见的用例。我所有的本地状态更改for循环都可以重新编写为递归,但很难看到它的好处。当我编写算法时,我的伪代码是本地状态改变,或者我正在移植的Fortran示例是本地状态改变,并且将其转换为递归函数会反映其含义,而不是将其强化。之后,编译器必须反转该过程,将其转换为看起来很像“直观”原始的机器代码,如果转换不完美,可能会失去效率。

    但另一方面,程序的大规模结构(不适合单个屏幕的所有内容)通过不可变数据结构和没有副作用的函数得到极大改善。在#3的情况下,我们仍然得到参考透明度(函数),类似Haskell的懒惰评估是可能的,我们获得了不可变数据的所有优点(所有值都是不可变的,虽然本地符号不是),我们也得到了平滑过渡到并行化,尽管粒度是一个函数。

    当然,我可以在自己的节目中做任何我想做的事情;我问这是否是一种常见的风格,如果它有一个名字,以及是否有任何支持/强制执行它的语言或库。 (Clojure瞬态是案例#2的一个例子,数据结构是暂时可变的.Clojure的with-local-vars模拟#3,但是有很多开销---它比Scala中的本地“var”慢得多,所以它没有以直接的方式转换为机器代码,我猜这是隐含在我要求的内容中。除此之外,我还没有找到任何示例。)

0 个答案:

没有答案