使用生成器和lambda,我们可以使用Python进行函数式编程。您也可以使用Ruby实现相同的功能。
所以问题是:为什么我们需要特定的功能编程语言,例如Erlang,Haskell和Scheme?这些特定的功能编程语言提供了什么不同?为什么我们不能只使用Python进行函数式编程?
使用生成器和lambda,我们可以使用Python进行函数式编程。您也可以使用Ruby实现相同的功能。
所以问题是:为什么我们需要特定的功能编程语言,例如Erlang,Haskell和Scheme?这些特定的功能编程语言提供了什么不同?为什么我们不能只使用Python进行函数式编程?
Answers:
我很欣赏这个问题,因为我个人非常喜欢Python和函数式编程。我有很长的Python背景,最近我开始学习Haskell,因此,根据我的个人经验,从功能的角度来看这些语言之间的区别,这里有几点。
纯度
即使您根本不关心函数的纯度(即没有副作用),它对于读取代码的难易程度和原因也有实际的影响。即使您在自己的Python函数中保持纯净,也要使编译器强制执行纯净,并且最重要的是,具有基于纯净和不可变数据结构构建的标准库也有很大的不同。
性能
您可能会或可能不会在乎性能,这取决于您的应用程序域是什么,但是与Python和其他动态语言相比,静态类型和有保证的纯度使编译器可以使用更多的功能(尽管我不得不承认PyPy的确很棒入侵,例如LuaJIT奇迹般地临近。
尾叫优化
与性能相关,但略有不同。即使您不太在意运行时性能,也没有进行尾部调用优化(尤其是尾部递归)会限制您在Python中实现算法的方式而不会达到堆栈限制。
句法
这就是为什么我开始看“真正的”功能语言而不是仅仅使用具有功能样式的Python的最大原因。尽管我认为Python通常具有非常有表现力的语法,但是它具有一些特定于函数编码的弱点。例如:
f = g . h
与f = lambda *arg: g(h(*arg))
f = map g
vs.f = functools.partial(map, g)
sum = reduce (+) lst
vs.sum = reduce(operator.add, lst)
y = func1 $ func2 $ func3 x
比容易阅读y = func1(func2(func3(x)))
。这些是最重要的区别:
哈斯克尔
Haskell和Erlang
Erlang
方案
所有语言
此外,您还应该看看ML系列中的语言,例如SML,Ocaml和F#和Scala,它们以一种新的方式融合了OO和功能编程。所有这些语言都有独特有趣的功能。
很难确切地定义“功能语言”是什么-在您列出的语言中,只有Haskell是纯粹的功能(所有其他语言都采用某种混合方法)。但是,某些语言功能对函数式编程非常有帮助,而Ruby和Python不足以成为FP的良好环境。这是我的个人清单,按重要性排序:
对(1)的需求应该很明显-如果没有一流的函数,高阶函数将非常困难。当人们谈论Ruby和Python是FP的好语言时,他们通常在谈论这一点。但是,此特定功能是必需的,但不足以使语言适合FP。
自从Scheme发明以来,(2)一直是FP的传统必需品。没有TCO,就不可能进行深度递归编程,深度递归是FP的基石之一,因为您会遇到堆栈溢出的情况。Clojure(由于JVM的限制)是唯一不具备此功能的(按流行的定义)语言(由于JVM的限制),但是Clojure具有多种可模拟TCO的技巧。(仅供参考,Ruby TCO是特定于实现的,但Python 特定地不支持它。)必须保证TCO的原因是,如果它是特定于实现的,则深度递归函数会因某些实现而中断,因此您不能真正做到这一点。完全使用它们。
(3)是现代功能语言(尤其是Haskell,Erlang,Clojure和Scala)具有Ruby和Python没有的另一大优点。无需赘述,保证不变性消除了所有类型的错误,尤其是在并发情况下,并且允许诸如持久数据结构之类的整洁事物。没有语言级别的支持,要利用这些好处是非常困难的。
对我而言,(4)是关于纯功能语言(与混合语言相对)最有趣的事情。考虑以下极其简单的Ruby函数:
def add(a, b)
a + b
end
这看起来像是一个纯函数,但是由于操作员重载,它可能会改变参数或导致副作用,例如打印到控制台。不太可能有人会给+
操作员带来过多的副作用,但是这种语言并不能保证。(这同样适用于Python,尽管可能不适用于此特定示例。)
另一方面,在纯功能语言中,存在语言级的保证,即功能是参照透明的。这具有许多优点:可以轻松记住纯功能;可以轻松测试它们,而无需依赖任何全局状态;函数中的值可以延迟或并行地求值,而不必担心并发问题。Haskell充分利用了这一点,但是我对其他功能语言的了解还不够,他们是否知道。
综上所述,几乎所有语言(甚至Java)都可以使用FP技术。例如,谷歌的MapReduce受到功能思想的启发,但是据我所知,他们的大型项目没有使用任何“功能”语言(我认为他们大多使用C ++,Java和Python)。
您提到的语言非常不同。
虽然Python和Ruby是动态类型的语言,但是Haskell是静态类型的。Erlang是一种并发语言,使用Actor模型,与您提到的所有其他语言有很大不同。
Python和Ruby具有许多命令式构造,而在像Haskell这样更纯净的功能语言中,一切都返回某种东西,换句话说,一切都是函数。
像往常一样晚参加聚会,但无论如何都要说些什么。
功能编程语言不是允许功能编程的语言。如果按照这个定义去做,那么几乎任何地方的任何语言都是一种功能性编程语言。(顺便说一句,同样适用于OOP。如果愿意,可以用C用OOP风格编写。因此,根据您的逻辑,C是一种OOP语言。)
使得功能性编程语言脱颖而出的并不是它允许您进行编程的方式,而是它使您可以轻松进行编程的方式。那是关键。
因此,Python具有lambda(它们是令人难以置信的类似于闭包的事务),并为您提供了一些库函数,这些库函数将在功能库中看到,例如“ map”和“ fold”。但是,这还不足以使其成为一种功能性的编程语言,因为很难以一致的功能风格一致地进行编程(而且该语言肯定不会强制采用这种风格!)。Python的核心是与状态和状态操纵操作有关的命令式语言,这与功能语言的表达式和表达式评估语义完全不同。
那么,当Python(或Ruby(或插入您选择的语言))可以“执行函数式编程”时,为什么我们有函数式编程语言呢?因为Python等无法进行适当的函数式编程。这就是为什么。
您可以使用Java进行函数式编程(请参见例如http://functionaljava.org/)。您也可以在C中进行面向对象的编程。这不是那么惯用。
因此,实际上我们并不是绝对不需要Erlang,Haskell,Scheme或任何特定的编程语言,但是它们都代表着不同的方法和不同的折衷,这使某些任务变得更容易,更难。您应该使用什么取决于您要实现的目标。
这个问题可以应用于无数种语言和范例。
大多数(如果不是全部)语言都是出于特定原因而存在的。它们之所以存在,是因为有人需要没有一种当前的语言能填补或填补不好的语言。(当然,这并不适用于每一种语言,但我觉得它适用于大多数知名的语言。)例如,蟒蛇最初是与阿米巴OS [接口1,2 ]和Erlang是为了帮助在电话应用开发中[ 3 ]。因此,一个问题的答案是“为什么我们需要另一种功能语言?” 可能很简单,因为[插入一个知道如何设计语言的人的名字]不喜欢python的方式。
这几乎可以概括我认为的答案。尽管您可以使用python做任何可以使用功能语言完成的事情,但您真的要这么做吗?您可以使用C进行的所有操作,都可以使用汇编进行的操作,但是您想这样做吗?不同的语言总是总是最擅长做不同的事情,这就是应该的方式。
lambda演算,LISP和Scheme中可用的每个概念都可以在Python中使用,因此,是的,您可以在其中进行函数式编程。是否方便,取决于上下文和品味。
您可以轻松地用Python(Ruby,Scala)编写LISP(或其他功能语言)解释器(这意味着什么?)。您可以使用纯功能为Python编写解释器,但是这需要大量工作。如今,即使是“功能性”语言也已成为多种范例。
这本古老而美丽的书提供了(尽管不是全部)大多数有关函数式编程本质的答案。
eval()
功能,即数据需要代码,但这是更进一步的:它使您可以像LISP中一样修改大多数运行时环境。
eval()
是运行时元编程。有时它很有用,但是却非常昂贵。Lisp宏是不同的,它是一个编译时的元编程。在Python中没有可用的任何可用形式。
因为Python可以还计划在非功能性的风格,这是不够好为FP纯粹。但是,更多实用的编码人员可以享受功能样式的好处,而不必执迷于此:
“功能程序员听起来像中世纪的和尚,否认自己过着快乐的生活,希望这会使他有德。对于那些对物质利益更感兴趣的人来说,这些“优势”并不是很令人信服。函数式程序员辩称存在巨大的物质利益…[但是]这显然是荒谬的。如果省略赋值语句带来如此巨大的收益,那么FORTRAN程序员将已经这样做了二十年。通过忽略功能(无论功能有多糟糕)来使语言更强大,这在逻辑上是不可能的。”
-John Hughes,为什么函数式编程很重要
goto
都是可怕的。
call-with-current-continuation
。