我读过一些有关声明式/函数式编程(语言)的文章,尝试过Haskell并自己编写了一篇。从我所看到的,函数式编程比经典的命令式样式有几个优点:
- 无状态程序;没有副作用
- 并发 在新兴的多核技术中发挥出色
- 程序通常较短,在某些情况下更易于阅读
生产率提高(例如:Erlang)
命令式编程是一个非常古老的范例(据我所知),可能不适合21世纪
为什么使用功能语言编写的公司或程序仍然如此“稀有”?
为什么在查看函数式编程的优势时,我们仍然使用命令式编程语言?
也许在1990年还为时过早,但是今天呢?
我读过一些有关声明式/函数式编程(语言)的文章,尝试过Haskell并自己编写了一篇。从我所看到的,函数式编程比经典的命令式样式有几个优点:
生产率提高(例如:Erlang)
命令式编程是一个非常古老的范例(据我所知),可能不适合21世纪
为什么使用功能语言编写的公司或程序仍然如此“稀有”?
为什么在查看函数式编程的优势时,我们仍然使用命令式编程语言?
也许在1990年还为时过早,但是今天呢?
Answers:
因为所有这些优点也是缺点。
无状态程序;没有副作用
现实世界中的程序都是关于副作用和突变的。用户按下按钮时是因为他们希望发生某些事情。当他们键入内容时,他们希望该状态替换以前存在的任何状态。当会计领域的简·史密斯结婚并更名为简·琼斯时,支持打印她的工资单的业务流程的数据库最好是处理这种突变。当您向外星人发射机枪时,大多数人并没有将其建模为建造生命值更少的新外星人。他们将其建模为现有外星人财产的变异。
当编程语言概念从根本上针对要建模的领域起作用时,很难证明使用该语言是合理的。
并发 在新兴的多核技术中发挥出色
问题刚刚解决。使用不可变的数据结构,您可以廉价使用线程安全,但要以处理过时的数据为代价。使用可变的数据结构,您将始终可以处理新数据,而不必编写复杂的逻辑来保持数据的一致性。并非其中一个明显优于另一个。
程序通常较短,在某些情况下更易于阅读
除非它们更长且更难阅读。学习如何阅读以功能风格编写的程序是一项困难的技能。人们似乎在构思程序方面要好得多,因为要遵循的一系列步骤(例如配方),而不是要进行的一系列计算。
生产率提高(例如:Erlang)
为了证明聘请知道如何以功能风格进行编程的程序员的巨额开销,生产力必须提高很多。
记住,您不想丢掉一个工作系统。大多数程序员不是从头开始构建新系统,而是维护现有系统,其中大多数是用非功能语言构建的。想象一下试图向股东证明这一点。您为什么要废弃现有的工资表系统以花费数百万美元构建一个新的工资表系统?“因为函数式编程太棒了”不可能使股东满意。
命令式编程是一个非常古老的范例(据我所知),可能不适合21世纪
函数式编程也很老。我看不出这个概念的年代如何相关。
不要误会我的意思。我喜欢函数式编程,我之所以加入这个团队是因为我想帮助将函数式编程的概念引入C#,并且我认为以不变的方式进行编程是未来的方式。但是以功能风格进行编程会产生巨大的成本,而这是不能简单地期望的。向功能性风格转变的过程将在数十年内逐步发生。就是这样:向更加实用的样式的转变,而不是全面拥抱Haskell的纯净和美丽以及放弃C ++。
我以编译器为生,我们肯定会为下一代编译器工具拥抱一种功能样式。这是因为函数式编程从根本上来说是我们面临的各种问题的良好匹配。我们的问题全都在于获取原始信息(字符串和元数据)并将其转换为不同的字符串和元数据。在发生突变的情况下,例如有人在IDE中键入内容,问题空间固有地适用于一些功能性技术,例如仅增量地重建树的部分。许多域没有这些使它们显然适合于功能样式的良好属性。
[哈斯克尔]
您为什么认为没有函数式编程语言进入主流?
约翰·休斯:行销不佳!我不是在宣传 我们有很多。我的意思是要仔细选择要占领目标市场的细分市场,然后做出坚定的努力,使功能编程成为迄今为止解决这一细分市场的最有效方法。在80年代的欢乐时光中,我们认为函数式编程对所有事物都有利,但是将新技术称为“对一切都有益”与将其称为“特别是一无是处”相同。品牌应该是什么?John Launchbury在ICFP的邀请演讲中非常清楚地描述了这个问题。Galois Connections的品牌是“功能语言的软件”时,差点破产,但是自从专注于“高安全性软件”以来,他们的实力越来越强。
许多人不知道技术创新是如何发生的,他们期望更好的技术将完全独自成为主导(“更好的捕鼠器”效应),但世界却并非如此。
根本的答案是不会替代,也不会替代-它们是具有不同优点和缺点的不同工具,哪种方法具有优势取决于项目和其他“软性”问题,例如可用的人才库。
我认为您是对的,当选择功能编程而不是其他样式时,由于多核而导致的并发性增长将提高(全球开发项目集)的百分比。
我认为今天很少见,因为当今的大多数专业人才最喜欢命令式和面向对象的技术。例如,我不止一次选择Java作为商业项目的语言,因为它足够好,没有争议,而且我知道我永远不会耗尽可以在其中进行编程(足够好)的人。
尽管功能编程有很多优势,但命令式和面向对象的编程永远不会完全消失。
命令式和面向对象的编程是对该问题及其解决方案的分步说明。这样,可以更容易理解。函数式编程可能有些晦涩。
最终,有用的程序将始终具有副作用(例如,向用户提供实际输出以供消费),因此,最纯粹的功能语言仍将需要一种不时进入命令式世界的方法。
当前的最新技术是命令式语言(例如C#)从功能世界(例如lambda语句)中借用功能,反之亦然。
不是吗
过去,Smalltalk是一个很棒的面向对象的系统。为什么没有采用面向对象的编程?好吧,它有。看起来不像Smalltalk。主流语言在C ++,Java,C#等语言中的应用越来越类似于Smalltalk。时尚和样式的变化比任何事物都慢,因此,当OO成为主流时,我们通过将OO的一部分粘合到旧语言中而获得了它,因此看起来就像C一样可以吞噬。
功能是相同的方式。Haskell是一种很棒的函数式语言。但是,与20年前相比,如今使用类C语法的主流程序员人数更多。因此它必须看起来像C。完成:查看任何LINQ表达式,并告诉我它不起作用。
dynamic
。这是这些功能中最多的Smalltalk-y,所以仅在这三种语言中最现代的最新版本中提供它就不足为奇了。:-)
我相信命令式语言之所以流行,仅仅是因为这是更多人习惯的。函数式编程和命令式编程模型都不比其他方法更晦涩难懂。实际上,它们是互补的。
一位发帖人说,命令性代码比功能性编程代码更容易理解。只有在读者已经看过命令性代码的情况下,这才是正确的,尤其是如果先前的示例是同一“系列”的一部分(例如C / C ++,Perl,PHP和Java)。我不会声称这对任何命令式语言都是正确的;比较Java和Forth,举一个极端的例子。
对于一个外行来说,所有编程语言都是难以理解的胡言乱语,也许是诸如Hypertalk和SQL之类的冗长语言除外。(值得注意的是,SQL是一种声明性和/或功能性语言,并且非常受欢迎。)
如果从一开始就接受过Lisp-y或Haskell-y语言的培训,我们都会认为函数式编程语言是完全正常的。
您已经获得了足够的答案,我仅会提及一些我尚未提及的事情。
首先(在我看来),程序语言从其通用性中受益匪浅。举个例子,几乎所有几乎在任何程度上都了解主流程序语言(或OO)的人都可以相当好地阅读其他大多数语言。我积极避免使用Java,C#,Cobol,Fortran或Basic(仅举几个例子),但可以很好地阅读它们中的任何一个-实际上,与每天使用它们的人一样,几乎可以阅读。
在功能方面,这是多真少。仅举例来说,我也可以相当合理地编写Scheme,但这在阅读Ocaml或Haskell时几乎没有用(仅用于几个示例)。即使在一个家庭中(例如,Scheme与Common Lisp),对一个人的熟悉程度似乎也不会很好地转化为另一个。
功能代码更具可读性的主张往往仅在狭窄的条件范围内才是正确的。对于非常熟悉该语言的人来说,可读性确实非常出色-但对于其他所有人而言,可读性通常几乎不存在。更糟糕的是,尽管过程语言的差异主要是语法,因此相对容易学习,但功能语言的差异通常更为根本,因此需要进行大量研究才能真正理解(例如,了解Lisp对理解Monad毫无帮助)。
另一个要点是,功能程序比程序程序短的想法通常更多地基于语法而不是语义。用Haskell编写的程序(例如)通常很短,但是它的功能只是其中很小的一部分。如果仅Haskell具有相对简洁的语法,这是非常重要的。
很少有纯粹的功能语言可以与APL争夺简洁的源代码(尽管公平地说,APL还支持创建更高级别的功能,因此与其他情况相比并没有太大的区别)。反之,阿达和C ++(仅几个例子)可以在必要的完成给定任务操作的数量方面相当有竞争力,但语法(至少通常)基本上更详细。
为什么函数式编程还没有被接管?
功能在某些方面更好,而在其他方面则更糟,因此它永远不会“接管”。它在现实世界中已经无处不在。
无状态程序;没有副作用
无状态程序更易于测试。现在,这已广为人知,并且在工业中经常被利用。
并发 在不断发展的多核技术中发挥出色的作用程序通常更短,在某些情况下更易于阅读生产率提高了(例如:Erlang)
您正在混合并发和并行性。
使用通信顺序过程(CSP)可以有效地完成并发。CSP中的代码可以更改其本地状态,但是在它们之间发送的消息应始终是不变的。
纯函数式编程在多核中的表现极差,因为它对缓存不友好。内核最终争夺共享内存,并且并行程序无法扩展。
为什么使用功能语言编写的公司或程序仍然如此“稀有”?
Scala通常被认为是一种功能性语言,但它的功能并不比C#(当今世界上最受欢迎的语言之一)更强大。
为什么在查看函数式编程的优势时,我们仍然使用命令式编程语言?
纯函数式编程有许多严重的缺点,因此我们使用不纯函数式语言,例如Lisp,Scheme,SML,OCaml,Scala和C#。
当我想到函数式编程可能给我的项目带来什么时,我总是沿着相同的思路走下去:
为了获得函数式编程的全部优势,您需要懒惰。是的,有严格的函数式语言,但是函数式编程的真正好处在严格的代码中也无法体现出来。例如,在Haskell中,很容易在列表上创建一系列惰性操作并将它们连接起来并将其应用到列表中。例如。op1 $ op2 $ op3 $ op4 $ someList
。我知道这不会建立整个列表,而在内部,我只会得到一个很好的循环,一次遍历所有元素。这使您可以编写真正的模块化代码。两个模块之间的接口可能涉及移交潜在的庞大数据结构,但是您不必一定要驻留该结构。
但是,当您懒惰时,就很难推理出内存使用情况了。更改Haskell编译器标志通常会将算法使用的内存量从O(N)更改为O(1),但有时不这样做。当您有需要最大程度地利用所有可用内存的应用程序时,这实际上是不可接受的,即使对于不需要所有内存的应用程序也不是很好。
两件事情: