锁定。这个问题及其答案被锁定,因为这个问题离题但具有历史意义。它目前不接受新的答案或交互。
我已经阅读了一些关于声明式/函数式编程(语言)的文章,尝试过 Haskell 以及自己编写的一篇。从我所见,函数式编程比经典的命令式编程有几个优点:
无状态程序;无副作用
并发;与新兴的多核技术配合得非常好
程序通常更短,在某些情况下更易于阅读
生产力提高(例如:Erlang)
命令式编程是一个非常古老的范例(据我所知),可能不适合 21 世纪
为什么使用函数式语言或编写程序的公司仍然如此“罕见”?
为什么在查看函数式编程的优势时,我们仍在使用命令式编程语言?
也许在 1990 年还为时过早,但今天呢?
因为所有这些优点也是缺点。
无状态程序;无副作用
现实世界的程序都是关于副作用和突变的。当用户按下按钮时,是因为他们想要某事发生。当他们输入某些内容时,他们希望该状态取代曾经存在的任何状态。当会计部门的简·史密斯结婚并改名为简·琼斯时,支持打印她的工资支票的业务流程的数据库最好全部用于处理这种突变。当你用机关枪对着外星人开火时,大多数人不会在脑海中将其视为建造一个生命值较低的新外星人。他们将其建模为现有外星人属性的突变。
当编程语言概念从根本上与被建模的领域相矛盾时,很难证明使用该语言是合理的。
并发;与新兴的多核技术配合得非常好
问题只是被推来推去。使用不可变数据结构,您可以以可能处理陈旧数据为代价获得廉价的线程安全性。使用可变数据结构,您可以始终处理新数据,但代价是必须编写复杂的逻辑以保持数据的一致性。这并不像其中一个明显比另一个更好。
程序通常更短,在某些情况下更易于阅读
除非它们更长且更难阅读。学习如何阅读以函数式风格编写的程序是一项艰巨的技能。人们似乎更善于将程序设想为一系列要遵循的步骤,就像一个食谱,而不是一系列要执行的计算。
生产力提高(例如:Erlang)
为了证明雇用知道如何以函数式编程的程序员的巨额费用,生产力必须提高很多。
记住,你不想丢掉一个工作系统;大多数程序员不是从头开始构建新系统,而是维护现有系统,其中大部分是用非函数式语言构建的。想象一下,试图向股东证明这一点。为什么你要放弃现有的工作工资系统,以花费数百万美元建造一个新系统? “因为函数式编程很棒”不太可能让股东高兴。
命令式编程是一种非常古老的范式(据我所知),可能不适合 21 世纪
函数式编程也很古老。我不明白这个概念的时代是如何相关的。
不要误会我的意思。我喜欢函数式编程,我加入这个团队是因为我想帮助将函数式编程的概念带入 C#,并且我认为不可变风格的编程是未来的方式。但是,不能简单地希望以函数式编程方式进行编程需要付出巨大的代价。在几十年的时间里,向更实用的风格转变将缓慢而逐渐地发生。它将是这样的:向更实用的风格转变,而不是全面拥抱 Haskell 的纯洁和美丽并放弃 C++。
我以构建编译器为生,我们肯定会接受下一代编译器工具的函数式风格。这是因为函数式编程从根本上很好地解决了我们面临的各种问题。我们的问题都是关于获取原始信息——字符串和元数据——并将它们转换成不同的字符串和元数据。在发生突变的情况下,比如有人在 IDE 中打字,问题空间固有地适用于功能技术,例如仅增量重建树中发生变化的部分。许多域没有这些使它们明显适合功能样式的良好属性。
Masterminds of Programming: Conversations with the Creators of Major Programming Languages
[Haskell] 为什么你认为没有函数式编程语言进入主流?约翰休斯:糟糕的营销!我不是说宣传;我们已经有很多了。我的意思是仔细选择要主导的目标市场利基市场,然后坚定地努力使函数式编程成为迄今为止解决该利基市场的最有效方法。在 80 年代快乐的日子里,我们认为函数式编程对一切都有好处——但称新技术“对一切都有好处”与称其“特别擅长什么”是一样的。品牌应该是什么?这是 John Launchbury 在 ICFP 受邀演讲中非常清楚地描述的一个问题。当 Galois Connections 的品牌是“功能语言的软件”时,他们几乎破产了,但自从专注于“高保证软件”以来,他们的实力越来越强。许多人不知道技术创新是如何发生的,并期望更好的技术会自行占据主导地位(“更好的捕鼠器”效应),但世界并非如此。
常见的答案是,两者都不会也不应该取代另一个——它们是不同的工具,具有不同的优缺点,哪种方法具有优势会因项目和其他“软”问题(如可用人才库)而异。
I think you're right that the growth of concurrency due to multi-core will increase the percentage (of the global set of development projects) when functional programming is chosen over other styles.
我认为今天这种情况很少见,因为今天的大多数专业人才库最熟悉命令式和面向对象的技术。例如,我不止一次选择 Java 作为商业项目的语言,因为它足够好、没有争议,而且我知道我永远不会用完可以用它(足够好)编程的人。
尽管函数式编程具有优势,但命令式和面向对象的编程永远不会完全消失。
命令式和面向对象的编程是对问题及其解决方案的逐步描述。因此,它可以更容易理解。函数式编程可能有点晦涩难懂。
最终,一个有用的程序总会有副作用(比如向用户提供实际输出以供消费),因此最纯粹的函数式语言仍然需要不时进入命令式世界的方法。
当前的最新技术是命令式语言(例如 C#)从函数世界(例如 lambda 语句)借用功能,反之亦然。
不是吗?
Smalltalk 在当时是一个很棒的面向对象系统。为什么没有面向对象编程?嗯,它有。它只是看起来不像 Smalltalk。主流语言与 C++、Java、C# 等变得更像 Smalltalk .
函数式也是一样。 Haskell 是一门很棒的函数式语言。但是,与 20 年前相比,今天我们有更多的主流程序员使用类 C 语法。所以它必须看起来像 C。完成:查看任何 LINQ 表达式并告诉我它不起作用。
dynamic
。这是这些功能中最符合 Smalltalk 的,所以我毫不奇怪它只出现在这三种语言中最现代的最新版本中。 :-)
我相信命令式语言更普遍,因为这是更多人习惯的。函数式编程和命令式编程模型都不比另一个更晦涩或学术。事实上,它们是互补的。
一位发帖人说,命令式代码比函数式编程代码更容易理解。这只有在读者已经看过命令式代码的情况下才是正确的,特别是如果前面的示例属于同一个“家族”(例如,C/C++、Perl、PHP 和 Java)。我不会声称任何命令式语言都是如此。拿Java和Forth做个比较,举个极端的例子。
对于外行来说,所有编程语言都是难以理解的胡言乱语,除了 Hypertalk 和 SQL 等冗长的语言。 (值得注意的是,SQL 是一种声明性和/或函数式语言,并且非常受欢迎。)
如果我们从一开始就接受过 Lisp-y 或 Haskell-y 语言的培训,我们都会认为函数式编程语言是完全正常的。
你已经得到了足够多的答案,我将只提及一些我还没有看到的事情。
首先,(在我看来)最重要的是,程序语言从它们的通用性中受益匪浅。例如,几乎任何了解几乎任何主流过程(或 OO)语言到几乎任何程度的人都可以相当好地阅读其他大多数语言。我积极避免使用 Java、C#、Cobol、Fortran 或 Basic(仅举几个例子),但可以很好地阅读它们中的任何一个——事实上,几乎和每天使用它们的人一样好。
在功能方面,这是不正确的。举个例子,我也可以相当合理地编写 Scheme,但这在阅读 Ocaml 或 Haskell 时用处不大(仅举几个例子)。即使在一个家族中(例如,Scheme vs.,Common Lisp),对一个家族的熟悉似乎也不能很好地转化为另一个家族。
函数式代码更具可读性的说法往往仅在狭窄范围的条件下才是正确的。对于非常熟悉该语言的人来说,可读性确实非常好——但对于其他所有人来说,它通常几乎不存在。更糟糕的是,虽然过程语言的差异主要在于语法,因此相对容易学习,但函数语言的差异往往更为根本,因此需要大量研究才能真正理解它们(例如,了解 Lisp 对理解 Monad 帮助不大)。
另一个主要观点是,函数式程序比过程式程序更短的想法通常更多地基于语法而不是语义。用 Haskell 编写的程序(例如)通常很短,但它的功能性只是其中的一小部分。如果仅仅是 Haskell 具有相对简洁的语法,那就太好了。
很少有纯函数式语言可以在简洁的源代码方面与 APL 竞争(不过,公平地说,APL 也支持创建更高级别的函数,因此与其他一些情况相比,这并没有太大的区别)。相反,Ada 和 C++(仅举几个例子)在完成给定任务所需的操作数量方面可能相当有竞争力,但语法(至少通常)要冗长得多。
无感知需求
我记得我的老上司 Rick Cline 在我给他看 John Backus 的图灵奖演讲的副本时的反应,题为 Can Programming Be Libered from the von Neumann Style?
他的回答是:“也许我们中的一些人不想从冯诺依曼风格中解放出来!”
为什么函数式编程还没有被接管?
功能性对某些事情更好,对其他事情更糟,因此它永远不会“接管”。虽然它在现实世界中已经无处不在。
无状态程序;无副作用
无状态程序更容易测试。现在,这在工业中得到了广泛的赞赏并经常被利用。
并发;与新兴的多核技术相得益彰程序通常更短,在某些情况下更易于阅读生产力提高(例如:Erlang)
您将并发和并行性混为一谈。
使用通信顺序进程 (CSP) 可以有效地完成并发。 CSP 中的代码可以改变其本地状态,但它们之间发送的消息应该始终是不可变的。
纯函数式编程在多核上的表现非常糟糕,因为它对缓存非常不友好。核心最终争夺共享内存,并行程序无法扩展。
为什么使用函数式语言或编写程序的公司仍然如此“罕见”?
Scala 通常被认为是一种函数式语言,但它并不比 C# 更实用,C# 是当今世界上最流行的语言之一。
为什么在查看函数式编程的优势时,我们仍在使用命令式编程语言?
纯函数式编程有很多严重的缺点,所以我们使用不纯的函数式语言,如 Lisp、Scheme、SML、OCaml、Scala 和 C#。
当我想到函数式编程可能会给我的工作项目带来什么时,我总是被引导到相同的思路上:
要获得函数式编程的全部优势,您需要惰性。是的,有严格的函数式语言,但函数式编程的真正好处在严格的代码中并不那么出色。例如,在 Haskell 中,很容易在列表上创建一系列惰性操作并将它们连接起来并将它们应用于列表。例如。 op1 $ op2 $ op3 $ op4 $ someList。我知道它不会构建整个列表,并且在内部我只会得到一个很好的循环,一次遍历一个元素。这使您可以编写真正模块化的代码。两个模块之间的接口可能涉及移交潜在的庞大数据结构,但您不必让结构常驻。但是当你有懒惰时,就很难推断内存使用情况。更改 Haskell 编译器标志会经常将算法使用的内存量从 O(N) 更改为 O(1),但有时不会。当您的应用程序需要最大限度地利用所有可用内存时,这是不可接受的,即使对于不需要所有内存的应用程序也不是很好。
两件事情:
无论技术有多好,都需要时间。 FP 背后的想法大约有 70 年的历史。但它在软件工程中(在战壕中,在工业中)的主流使用可能不到 10 年。要求开发人员采用全新的思维方式是可能的,但这需要时间(很多很多年)。例如,OOP 在 1980 年代初期确实得到了主流使用。然而,它直到 1990 年代后期才占据主导地位。你需要人们在它大受欢迎之前被迫面对它的力量。目前,人们正在使用不利用并行性的工具,并且一切正常。当不使用并行的应用程序变得难以忍受时;那么很多人将被迫使用并行工具,而 FP 可能会迅速流行起来。这也可能适用于 FP 的其他优势。
不定期副业成功案例分享