为什么要使用函数式编程语言?

346

我在这里看到很多关于函数式编程语言的讨论。为什么要使用它们而不是“传统”的编程语言?它们做得比传统语言好在哪里?它们又有什么劣势?最适合使用函数式编程的应用是什么?


John Hughes 写了一篇关于这个的论文:函数式编程的重要性 - Hjulle
一个代码示例,展示了如何从结构化编程转变为过程式编程,再到面向对象编程,最后到函数式编程。https://medium.com/@elye.project/why-code-evolve-from-procedural-to-object-oriented-to-functional-programming-13a88292307e?source=friends_link&sk=84f7fa01c79ef45c0db688d0e8ce3cc6 - Elye
47个回答

223
功能性编程使用不同于命令式和面向对象语言的范式。它们使用无副作用函数作为语言中的基本构建块。这使得很多事情成为可能,也使很多事情更加困难(或者在大多数情况下与人们所习惯的不同)。
函数式编程最大的优点之一是无副作用函数的执行顺序并不重要。例如,在Erlang中,这被用来以非常透明的方式实现并发。
由于函数式语言中的函数行为与数学函数非常相似,因此将其翻译成函数式语言很容易。在某些情况下,这可以使代码更易读。
传统上,函数式编程的一个主要缺点也是缺乏副作用。没有I/O很难编写有用的软件,但是在函数中实现I/O又很难。因此,大多数人从函数式编程中获得的只是计算单个输入的单个输出。在像F#Scala这样的现代混合范式语言中,这变得更加容易。
许多现代语言具有来自函数式编程语言的元素。C#3.0具有许多函数式编程功能,并且您也可以在Python中进行函数式编程。我认为函数式编程流行的原因主要是两个原因:并发问题在正常编程中越来越成为真正的问题,因为我们越来越多地使用多处理器计算机;以及语言变得更加易于访问。

17
你可以在Python中进行函数式编程,但效果不佳。 - Gordon Gustafson
30
在纯函数式编程语言中编写IO代码并不难。这些语言都提供了一种与命令式语言类似的简单机制来编写IO代码。它们所做的只是强制你不能在其接口声明为不执行IO的其他代码中调用IO代码。一个比喻是动态语言程序员抱怨静态类型语言(如Java)使她难以从方法返回任何想要的类型,因为她必须返回声明的类型。 - Ben
9
Haskell是一种纯函数式语言的例子,它没有你所说的缺点。实际上,它让处理副作用变得更加容易,因为副作用被封装了起来,并使程序员能够实现比命令式语言更强大的抽象水平... 实际上,每个人都应该尝试一下Haskell,真正掌握它,并意识到它为何如此强大。 - FtheBuilder

202
我认为函数式编程的方式已经被使用了40年,因此它已经成为编程风格之一,所以它不需要流行起来。每当面向对象编程员编写偏爱不可变对象的干净代码时,该代码都会借鉴函数式概念。
然而,当前强制执行函数式编程样式的语言正受到广泛关注,这些语言是否会在未来成为主流仍是一个未知数。我个人怀疑,混合的、多范式的语言,如ScalaOCaml,将可能在纯函数式语言中占主导地位,就像纯面向对象语言(Smalltalk,Beta等)影响了主流编程,但最终并没有成为最广泛使用的符号一样。
最后,我不能抵制指出你对FP的评论与我听到的程序设计师不同几年前的话高度相似:
  • (我认为是神话的)“普通”程序员不理解它。
  • 它没有被广泛教授。
  • 你可以用当前技术以其他方式编写任何你能用它编写的程序。

正如图形用户界面和"代码作为业务模型"的概念帮助面向对象编程变得更加广泛接受一样,我相信更多地使用不可变性和简单的(大规模)并行将有助于更多的程序员看到函数式方法所提供的好处。但是尽管我们在过去50年左右的数字计算机编程历史中学到了很多东西,我认为我们仍然有很多需要学习的。二十年后,程序员们将惊叹于我们当前正在使用的工具的原始性质,包括现在流行的面向对象和函数式语言。


55
只要回顾20年前,我认为编程并没有太大的进步。虽然我们有了更好的工具,可能会有一两种新的语言,但基本上不会有太多的改变。这需要超过20年的时间。我们曾经都以为在2000年能看到飞行汽车。 :) - bibac
33
O'Caml 是爱尔兰人。 - defmeta
7
“推崇不可变性”和“避免副作用”这两个规则在面向对象编程和命令式编程领域已经成为很长一段时间以来的良好经验法则。(那还有什么不喜欢的呢?;-) - joel.neely
102
20年前我们写C代码,讨论Clipper或Turbo Pascal的优点。面向对象编程是学术领域的专属领域。认为现在没有什么变化是完全荒谬的。 - Daniel C. Sobral
24
@Daniel:请列出那些为“Clipper有利之处”辩护的人名单。他们需要被追捕并绳之以法。 - David
显示剩余10条评论

126

对我而言,它最大的优势在于其内在的并行性,尤其是现在我们正在从更高的CPU时钟频率向更多的核心方向发展。

我不认为它会成为下一个编程范式并彻底取代面向对象的方法,但我认为我们将达到这样一个点:要么我们需要在一个函数式语言中编写部分代码,要么我们的通用目的语言将增加更多的函数式结构。


4
我们已经看到这种情况正在发生,而且未来会更加普遍。因此,我在这一点上完全同意。 - Jason Baker
棘手的问题在于,FP 的共享无 / 无副作用方面使其非常适合并行处理。而这些方面与 OO 解决方案不太相符 - 制作有效的混合体是非常困难的。也许可以使用 FP 粘合剂连接 OO 节点? - James Brady
对于一个有效的混合编程,请查看D编程语言的2.0分支。它是一个alpha/正在进行中的工作,但已经到达那里了。 - dsimcha
2
我觉得这个答案很有趣,虽然我不懂任何函数式语言,但为什么它们被认为更适合并行处理呢? - andandandand
26
由于没有共享数据,函数没有副作用。你所关心的只有返回值。(这对于面向对象/过程化程序员来说可能是一个比较难理解的概念。)因此,许多函数可以同时调用,只要一个函数的输出不被另一个函数用作输入。 - Tom Smith
Erlang和Elixir是功能语言,因其对并发的惊人支持而广受欢迎。 - Nahiyan

79
即使你从未在职业上使用过函数式语言,了解函数式编程也会让你成为更好的开发人员。它将为您的代码和程序设计提供新的视角。
我认为学习它没有任何理由。我认为那些很好地混合了函数式和命令式风格的语言最有趣,也最有可能成功。

很好的观点,但我想看到一个解释,“它会以什么方式让你成为更好的开发者”。 - mt3
20
不同的编程范式从不同角度解决问题,通常需要“不同的思考方式”或心态。 而训练自己以多种不同的思维方式(意味着学习在哪种情况下使用哪种方式...)从来都不是一件坏事。 - peSHIr

59

我总是对下一个大事件持怀疑态度。很多时候,不管技术是否好,下一个大事件都是历史的纯粹偶然,恰好在正确的时间和地点出现。例如:C ++ ,Tcl/Tk,和Perl。它们都是有缺陷的技术,但因为它们被认为要么解决了当今的问题,要么与根深蒂固的标准几乎相同,所以它们都非常成功。函数式编程确实可能很棒,但这并不意味着它会被采用。

但我可以告诉你为什么人们对函数式编程感到兴奋:许多程序员都有一种“转化体验”,他们发现使用函数式语言可以使他们的生产力提高一倍(或者可能是十倍),同时生成的代码更具有抗变性和更少的错误。这些人认为函数式编程是一种秘密武器;Paul GrahamBeating the Averages就是这种心态的一个很好的例子。哦,还有他的应用程序?电子商务网站应用。

自2006年初以来,函数式编程和并行性也引起了一些关注。由于像Simon Peyton Jones这样的人从至少1984年开始就一直担心并行性问题,所以在函数式语言解决多核问题之前,我不会抱太大希望。但这解释了现在出现的一些额外的关注。

总的来说,美国大学在教授函数式编程方面做得不太好。他们有强烈的支持使用Scheme教授入门编程},{{link2:Haskell也得到了一些支持,但是在教授函数式程序员的高级技术方面却很少。我曾在哈佛大学教过这样的课程,并将在塔夫茨大学再次教授。本杰明·皮尔斯曾在宾夕法尼亚大学教授过这样的课程。我不知道保罗·赫达克耶鲁大学是否有所作为。相比之下,欧洲大学在这方面做得更好;例如,在丹麦、荷兰、瑞典和英国的重要地方都强调函数式编程。我对澳大利亚的情况了解较少。

@John:「面向对象编程优先」曾经很流行,但现在似乎不再受欢迎了。编译器课程的种类繁多,我不敢概括——而且,很多学生从未学过编译器。 - Norman Ramsey
29
我在澳大利亚上大学时学习了Java/C++,但我的一些同事去了不同的大学,在那里他们学了几个Haskell单元。它被用于编程入门和其中一个最后一年的单元。当我的同事第一次接触强制转换(此时他只知道Haskell)时,他对Java讲师说了一句话,我笑了——“什么?!你意思是你有一个东西,你不知道它是什么类型?!” - Jacob Stanley
1
看看C#语言中有那么多欧洲人在团队里,发生了什么事情 :) - Benjol
在加州大学伯克利分校,入门课程基于Scheme语言,并开始集中讲授函数式编程。面向对象编程将在以后进行介绍,但到目前为止,它已经为我提供了非常好的函数式语言概述以及使用它们的好处。我的教授布莱恩·哈维博士在这里教授材料非常好,可能会让一些人使用函数式语言;然而,他即将退休,所以谁知道接下来会发生什么... - Tikhon Jelvis
你对“下一个大事物”持怀疑态度吗?函数式编程至少自1958年(Lisp)以来就存在了。说函数式编程是下一个大事物,你是什么意思? - Lysenko Andrii
显示剩余5条评论

32

我没有看到有人提到房间里的大象,所以我认为这是我的责任 :)

JavaScript (JS)是一种函数式语言。随着越来越多的人使用JS进行更高级的操作,特别是利用jQueryDojo Toolkit和其他框架的高级功能,函数式编程(FP)将通过Web开发人员的后门引入。

与闭包结合使用,FP使JS代码变得非常轻巧,但仍然易读。


2
这就是我真正开始深入了解函数式编程的方式。没有什么比Prototype.js的list.each(function(item){})或jQuery的整个操作方法更好的了。 - Cory R. King
20
Javascript允许以函数式编程的方式进行编程。然而,它是一种跨范式语言,允许以多种不同的方式编程(我比较喜欢这种方式,但这并不重要)…… 面向对象,函数式,过程式等。 - RHSeeger
+1,请查看http://codex.sigpipe.cz/zeta/。 - just somebody
jQuery对象方法只是列表单子中的操作。以表示容器(或序列)的对象作为输入并返回对象容器作为输出,这是一个实用的fmap实现的好例子。 - Jared Updike

26
大多数应用程序都足够简单,可以使用普通的面向对象方式解决问题。
面向对象的方式并不总是“正常”的。这十年的标准可能会成为上一个十年被边缘化的概念。
函数式编程是数学。保罗·格雷厄姆在Lisp上的看法(将Lisp替换为函数式编程):
因此,这个20世纪50年代的语言之所以没有过时,短暂的解释是它不是技术,而是数学,而数学不会过时。要比较Lisp的正确方法不是与20世纪50年代的硬件相比,而是与1960年发现的Quicksort算法相比,后者仍然是最快的通用排序算法。

25

10
JavaScript被认为是一种函数式编程语言,因为它支持函数作为一等公民,并且具有高阶函数、闭包和递归等函数式编程概念。此外,JavaScript还具有不可变性和纯函数的特性,这些也是函数式编程的核心原则之一。 - Pacerier
11
它具有一流函数,高阶函数,闭包,匿名函数,部分应用,柯里化和组合。 - daniel1426
2
哈哈。曾经写过一个比屏幕还要宽的带有嵌套函数的负载偿还Excel公式。当时我有点意识到自己在进行函数式编程,但还不知道这个术语。 - ProfK
7
请将C添加到那个列表中。 - Mandeep Janjua
3
嗯?怎么了?为什么不是任何语言呢? - Sz.
显示剩余3条评论

18

一般的企业程序员,比如我所工作的大多数人,不会理解它,而且大多数的工作环境也不允许你用它来编程。

然而这只是一个时间问题。普通的企业程序员会学习当前流行的技术。15年前,他们还不懂面向对象编程。
如果 函数式编程流行起来,那么“普通企业程序员”也会跟随潮流。

它并没有被大学教授(或现在是否有?)

这各大学不太一样。在我的大学里,SML 是学生们首先接触的语言。

我相信MIT教授Lisp作为第一年课程。当然,这两个例子可能不代表全部情况,但我相信大多数大学至少会提供一些函数式编程的选修课程,即使他们不把它作为强制性的课程内容。

大多数应用程序都足够简单,可以通过普通的面向对象方式解决

然而这并不仅是“是否足够简单”的问题。使用函数式编程是否会使解决方案更加简单(或者更易读、更健壮、更优雅或者更高效)?很多事情“可以通过Java来解决”,但是仍需要大量的代码。

总之,需要记住的是,函数式编程支持者已经声称它是下一个大潮流已经好几十年了。也许他们是正确的,但需要注意的是,当他们在5年、10年或15年前做出同样的声明时,其实并不正确。

但他们的优点之一,最近C#朝着函数式编程方向迅速发展,以至于它几乎将一代程序员变成了函数式编程程序员,甚至他们自己都没有注意到。这可能会为函数式编程“革命”铺平道路。也许吧。 ;)


MIT以前在其计算机科学入门课程中教授Scheme,但现在使用Python。 - mipadi
1
"15年前,他们不理解面向对象编程(OOP)的概念。问题在于,15年前他们也不理解函数式编程(FP)的概念。而今天,他们仍然不理解。" - Jason Baker

15

如果一个人无法看到其他艺术形式的价值,他就无法理解自己选择的艺术作品的完美与不足。遵循规则只能使技术发展到一定程度,然后学生和艺术家必须学习更多并寻求进一步发展。因此,研究除策略之外的其他艺术形式是有意义的。

通过观察他人的活动,谁没有学到更多关于自己的东西呢?要学剑,就应该学吉他。要学拳,就应该学商业。仅仅学习剑道会让你心胸狭隘,并阻止你向外扩展。

--宫本武藏,《五轮书》



网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接