为什么还没有接受函数式编程呢?

时间:2010-05-14 16:24:04

标签: functional-programming

我已经阅读了一些关于声明/函数编程(语言)的文章,尝试过Haskell以及自己编写的文本。从我所看到的,函数式编程比传统的命令式风格有几个优点:

  • 无国籍项目;无副作用
  • 并发;使用不断增长的多核技术,玩得非常好
  • 程序通常更短,在某些情况下更容易阅读
  • 生产力提高(例如:Erlang)

  • 命令式编程是一个非常古老的范例(据我所知),可能不适合21世纪

为什么公司使用或以函数式语言编写的程序仍然“罕见”?

为什么在查看函数式编程的优点时,我们仍在使用命令式编程语言吗?

也许现在它在1990年还为时尚早,但今天呢?

11 个答案:

答案 0 :(得分:530)

因为所有这些优点也是不利的。

  

无国籍计划;没有副作用

现实世界的计划都是关于副作用和突变。当用户按下按钮时,因为他们想要发生某些事情。当他们输入某些内容时,他们希望该状态替换曾经存在的状态。当Jane Smith在会计中结婚并将她的名字改为Jane Jones时,支持打印她的薪水的业务流程的数据库最好是处理那种突变。当你向外星人发射机枪时,大多数人并没有在精神上建模那个具有较少生命值的新外星人的建造;他们将其模型化为现有外星人属性的变异。

当编程语言概念从根本上不利于被建模的域时,很难证明使用该语言是合理的。

  

并发;使用不断增长的多核技术,玩得非常好

问题就在于此。使用不可变数据结构,您可以以可能使用陈旧数据为代价来获得廉价的线程安全性。使用可变数据结构,您可以始终处理新数据,但必须编写复杂的逻辑以保持数据的一致性。它并不像其中一个明显优于另一个。

  

程序通常更短,在某些情况下更容易阅读

除非它们更长且更难阅读。学习如何阅读以功能风格编写的程序是一项艰巨的任务;人们似乎更善于将程序设想为一系列要遵循的步骤,比如一个配方,而不是作为一系列计算来进行。

  

生产力提高(例如:Erlang)

为了证明招聘那些知道如何以功能方式编程的程序员的大量费用,生产力必须上升很多。

请记住,你不想丢掉一个有效的系统;大多数程序员不是从头开始构建新系统,而是维护现有系统,其中大多数都是用非功能语言构建的。想象一下,试图向股东证明这一点。为什么要废弃现有的工作薪资系统,以数百万美元的价格建造一个新工资? “因为功能性编程非常棒”,不太可能让股东高兴。

  

命令式编程是一个非常古老的范例(据我所知)并且可能不适合21世纪

功能编程也很老。我不明白这个概念的时代是如何相关的。

别误会我的意思。我喜欢函数式编程,我加入了这个团队,因为我想帮助将函数式编程的概念引入C#,我认为以不可变的风格编程是未来的方式。但是,功能风格的编程需要付出巨大的代价,而不能简单地将其抛弃。向更具功能性的风格的转变将在几十年的时间里缓慢而渐进地发生。这就是它的本质:向更具功能性的风格转变,而不是批判性地接受Haskell的纯洁和美丽以及放弃C ++。

我以构建编译器为生,我们绝对拥抱下一代编译器工具的功能风格。那是因为函数式编程从根本上说是我们遇到的各种问题的良好匹配。我们的问题都是关于获取原始信息 - 字符串和元数据 - 并将它们转换为不同的字符串和元数据。在发生突变的情况下,就像有人在IDE中输入一样,问题空间固有地适用于功能性技术,例如逐步重建仅改变树的部分。 许多域没有这些很好的属性,使它们显然适合功能样式

答案 1 :(得分:38)

Masterminds of Programming: Conversations with the Creators of Major Programming Languages

  

[哈斯克尔]

     

为什么你认为没有函数式编程语言进入主流?

     

John Hughes:营销不佳!我不是指宣传;我们已经有了很多。我的意思是谨慎选择目标市场利基来支配,然后坚定不移地努力使功能性编程成为解决这一利基的最有效方式。在80年代的快乐时光中,我们认为函数式编程对一切都有好处 - 但是将新技术称为“对所有事情都有益”就像称之为“特别好无所求”一样。该品牌应该是什么?这是John Launchbury在他在ICFP的邀请演讲中非常清楚地描述的一个问题。当他们的品牌是“功能语言软件”时,Galois Connections几乎陷入困境,但他们因为专注于“高保证软件”而不断壮大。

     

许多人不知道技术创新是如何发生的,并期望更好的技术本身就会成为主导("better mousetrap"效应),但世界并不是那样。

答案 2 :(得分:27)

股票答案是既不会也不应该取代另一个 - 它们是具有不同优点和缺点的不同工具,哪种方法的优势会因项目和其他“软”问题而有所不同人才库。

我认为,当选择函数式编程而不是其他样式时,由多核引起的并发性增长将增加(全局开发项目集)的百分比,这是对的。

我认为今天这种情况很少见,因为今天的大多数专业人才库最适合使用命令式和面向对象技术。例如,我不止一次选择Java作为商业项目的语言,因为它足够好,没有争议,我知道我永远不会用完可以编程(足够好)的人。

答案 3 :(得分:26)

尽管功能编程具有优势,但命令式和面向对象编程永远不会完全消失。

命令式和面向对象编程是对问题及其解决方案的逐步描述。因此,可以更容易理解。功能编程可能有点模糊。

最终,一个有用的程序总是会产生副作用(比如向用户提供实际输出以供消费),因此最纯粹的函数式语言仍然需要一种不时进入命令式世界的方法。

当前最先进的技术是命令式语言(例如C#)从功能世界借用功能(例如lambda语句),反之亦然。

答案 4 :(得分:21)

不是吗?

Smalltalk在当天是一个伟大的面向对象系统。为什么没有接管面向对象的编程?好吧,它有。它看起来不像Smalltalk。主流语言随着C ++,Java,C#等变得越来越像Smalltalk。时尚和风格变化比任何东西都要慢,所以当OO成为主流时,我们通过将部分OO粘贴到旧语言上来获得它,所以它看起来像C一样吞下去

功能是一样的。 Haskell是一种很棒的函数式语言。但是,与20年前相比,我们今天使用类似C语法的主流程序员更多。因此它必须看起来像C.完成:查看任何LINQ表达式并告诉我它不起作用。

答案 5 :(得分:15)

我认为命令式语言更为普遍,因为这是更多人习惯的。函数式编程和命令式编程模型都不比其他模式更模糊或更具学术性。事实上,它们是互补的。

一张海报说,命令式代码比函数式编程代码更容易理解。只有当读者已经看到命令性代码时才会这样,特别是如果先前的示例是同一“族”的一部分(例如,C / C ++,Perl,PHP和Java)。我不会声称​​任何命令式语言都是如此;比较Java和Forth,做一个极端的例子。

对于外行来说,所有编程语言都是难以理解的乱码,除了可能是Hypertalk和SQL等冗长的语言。 (值得注意的是,SQL是一种声明性和/或功能性语言,并且非常受欢迎。)

如果我们从一开始就接受过Lisp-y或Haskell-y语言的培训,我们都认为函数式编程语言是完全正常的。

答案 6 :(得分:14)

你已经得到了足够多的答案,我只提到了一些我还没有提到的事情。

首先,(在我看来)最重要的是,程序语言从它们的共同程度中获益匪浅。举一个例子,几乎任何知道几乎任何主流程序(或OO)语言几乎任何程度的人都可以很好地阅读其他大部分语言。我主动避免使用Java,C#,Cobol,Fortran或Basic(仅举几个例子),但可以很好地阅读它们中的任何一个 - 实际上,就像每天使用它们的人一样。

在功能方面,很多不那么真实。例如,我也可以非常合理地编写Scheme,但这在阅读Ocaml或Haskell时几乎没用(仅举几个例子)。即使在一个家庭中(例如,Scheme vs. Common Lisp),对一个家庭的熟悉程度似乎也不能很好地转化为另一个家庭。

功能代码更具可读性的说法只有在狭窄的条件下才会成立。对于那些对语言非常熟悉的人来说,可读性确实很好 - 但对于其他人来说,它通常几乎不存在。更糟糕的是,虽然程序语言的差异主要是语法,因此相对容易学习,但功能语言的差异往往更为基础,因此需要大量的学习才能真正理解(例如,知道Lisp对理解Monads没什么帮助)。 / p>

另一个要点是函数式程序比程序性程序更短的想法通常更多地基于语法而不是语义。用Haskell编写的程序(例如)通常很短,但它的功能只是其中很小的一部分。如果仅仅是Haskell具有相对简洁的语法,那就太多了。

很少有纯粹的函数式语言可以与APL很好地竞争简洁的源代码(但是,公平地说,APL也支持创建更高级别的函数,因此在其他情况下并没有那么大的差异)。相反,Ada和C ++(仅举几个例子)在完成给定任务所需的操作数量方面具有相当的竞争力,但语法(至少通常)基本上更详细。 / p>

答案 7 :(得分:11)

没有感知需要

我回忆起我老Boss Rick Cline的回应,当时我向他展示了John Backus'图灵奖的演讲稿,题为可以从冯·诺依曼风格中解放编程吗?

他的回答:“也许我们中的一些人希望从冯·诺依曼风格中解放出来!”

答案 8 :(得分:10)

  

为什么还没有接受函数式编程呢?

功能对于某些事情更好,对其他事情更糟,因此它永远不会“接管”#34;。它在现实世界中已经无处不在。

  

无国籍计划;没有副作用

无状态程序更容易测试。现在,人们普遍认可并经常在工业中使用它。

  

并发;采用不断增长的多核技术,发挥得非常好   程序通常较短,在某些情况下更容易阅读   生产力提高(例如:Erlang)

您正在混淆并发和并行。

使用通信顺序进程(CSP)可以有效地完成并发。

> CSP中的代码可以改变其本地状态,但它们之间发送的消息应始终是不可变的。

纯功能编程在多核中的表现非常糟糕,因为它对缓存不友好。核心最终争夺共享内存,而并行程序无法扩展。

  

为什么公司使用或以函数式语言编写的程序仍然如此"罕见"?

Scala通常被认为是一种功能语言,但它并不比C#更具功能性,C#是当今世界上最流行的语言之一。

  

为什么在查看函数式编程的优点时,我们仍在使用命令式编程语言吗?

纯粹的函数式编程有很多严重的缺点,因此我们使用不纯的函数式语言,如Lisp,Scheme,SML,OCaml,Scala和C#。

答案 9 :(得分:7)

当我想到函数式编程可能会给我的项目工作带来什么时,我总是引导思维方式:

  1. 要获得功能编程的全部优势,您需要懒惰。是的,有严格的函数式语言,但函数式编程的真正好处并没有在严格的代码中发挥作用。例如,在Haskell中,很容易在列表上创建一系列延迟操作并将它们连接起来并将它们应用到列表中。例如。 op1 $ op2 $ op3 $ op4 $ someList。我知道它不会构建整个列表,而在内部我只是要获得一个很好的循环,一次一个地遍历元素。这允许您编写真正模块化的代码。两个模块之间的接口可能涉及移交潜在的大量数据结构,但您不必将结构驻留在其中。

  2. 但是当你有懒惰时,很难推断内存的使用。更改Haskell编译器标志经常会将算法使用的内存量从O(N)更改为O(1),有时则不会。当你的应用程序需要最大限度地利用所有可用内存时,这是不可接受的,即使对于不需要所有内存的应用程序也不是很好。

答案 10 :(得分:6)

两件事:

  1. 无论技术有多好,都需要时间。 FP背后的想法已有70年历史。但它在软件工程(在战壕,工业中)的主流使用可能不到10年。要求开发人员采用种族新思维模式是可能的,但这需要时间(很多年)。例如,OOP在20世纪80年代初确实成为主流用途。然而,直到20世纪90年代后期它才获得了宿舍。
  2. 你需要让人们在遇到技术之前被迫面对技术的力量。目前,人们正在使用不能利用并行性的工具,而且工作正常。当不使用并行性的应用变得难以忍受时;然后很多人将被迫使用并行工具,FP可能会大受欢迎。这也可能适用于FP的其他优势。