对函数式编程的误解

最近,我偶然看到了这样一篇文章:实用的纯函数式编程,里面谈到了函数式编程的优势。然而,作者的某些对函数式编程的思想认识却让我诧异:

“长期的处在命令式编程的环境世界里会让我们养成一种特定的顺序式的思考方式 … 而另一边,在纯函数的世界里,我们被强迫去思考的是如何变换数据。”

作者辩论说,按照代码序列来思考程序执行的思考方式是命令式编程语言固有的特征。文章中给出的第一个“命令式”的例子是一个简单的Java循环:

1  int sum(int[] list) {
2	  int result = 0;
3	  for (int i : list)
4	    result += i;
5	  return result;
6	}

问题在于,我可以用纯函数编程语言写出相同形式的这个例子。当然,这代码跟Haskell语言代码不是很相似,但你要知道,Haskell并不是唯一的纯函数编程语言。例如,下面的这段代码:

1	int sum([int] list):
2	    result = 0
3	    for i in list:
4	        result = result + i
5	    return result

这是一个最严格意义上的纯函数(针对相同的输入永远都产生相同的输出,没有副作用,而且具有亲系透彻性(referentially transparent)的。)这个函数是纯函数,这是因为复合数据结构(例如list,set,map等)具有值语义(value semantics),它们的行为跟基本数据结构(例如int)一样,而不是类似Java里的那种对数据的引用。

函数式风格

我认为作者在文章里把函数式语言和函数式风格(以函数为主要表达形式和计算方式)混淆了。没错,函数式风格更倾向于使用递归而不是循环。但这并不阻碍着函数式语言里使用循环结构。

关键还在于,很多命令式语言里支持函数式编程风格。换句话说,它不是函数式编程语言的专利(尽管它们更适合)。我们应该清楚的区分这两个概念,从而避免对函数式编程语言和命令式编程语言之间的不同产生混淆。

问题是有些人并不喜欢函数式风格。例如,我更喜欢使用循环(比如上面的sum()例子里),因为这样更加清晰,好理解。但是,对于有些东西(例如遍历一个列表),我认为用递归更好。这是我的风格。。问题是,人们通常会认为,那些具有命令式编程习惯的人应该完全的转换成函数式编程语言风格。但事实上不需要这样。一些主流的函数式编程语言故意给命令式编程制造障碍。如果事情能变的简单点,人们会慢慢的转变他们的编程习惯,而不需要形式上的强迫…

你对此有想法吗?

[英文原文:A Misconception of Functional Programming? ]
分享这篇文章:

16 Responses to 对函数式编程的误解

  1. david says:

    先占了沙发再说

  2. paladin_t says:

    赞同!现在在C#里偶尔混用lambda、Action、Func、匿名函数、闭包用的很嗨。

  3. 依云 says:

    对于求和,我认为用 sum 函数最好,哈哈哈~我用 Python 或者 Haskell,才不要用麻烦到死的 Java 呢 😀

  4. 唐海康 says:

    1 int sum([int] list):
    2 result = 0
    3 for i in list:
    4 result = result + i
    5 return result
    这段代码是Haskell语言写的吗,没看过表示不清楚,但在我已知的函数式语言如erlang语言里面,这么写是有问题的啊。result = result + i ,就没人吐槽这一句吗,函数式风格的变量貌似都只能绑定一次啊。还是说想用一句命令式来说明命令式也可以是纯函数啊?
    首先这根本就不是函数式啊,函数式里面混搭我是觉得没问题,但是那就不叫函数式了,而是想C++那样是多范式了啊。
    作者给了这个例子我就不清楚要说明的是什么了= =

  5. 依云 says:

    aqee 你给我出来!我是说我怎么看不懂呢,side effect 是经济学里的 marginal utility 吗?作者都给出了维基百科链接,左边看看中文的链接到哪里会失恋啊?

  6. junepeng says:

    博主,我想请教个问题,你左边这个微博转发次数,是怎么获取到的啊,我在新浪微博开发平台没找到。

  7. haskell says:

    赞同!支持作者

  8. 魔亦神 says:

    result = result + i

    这也是函数式?请楼主指明这是哪一种“纯函数编程语言”

  9. toshio says:

    Sum([]) -> 0;
    Sum([Num|List]) -> B + Sum(List).

    这样?

  10. brave_bang 对这篇文章的反应是飘过~
  11. xx 对这篇文章的反应是笑死了
  12. xx 对这篇文章的反应是垃圾

发表评论

邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据