函数式编程:修订间差异

求闻百科,共笔求闻
添加的内容 删除的内容
(机器人:将英文日期转换为ISO格式)
(机器人:清理不当的来源、移除无用的模板参数)
 
第22行: 第22行:
{{cite journal|author = John McCarthy||title=Recursive functions of symbolic expressions and their computation by machine, Part I.|journal=Communications of the ACM|volume=3|issue=4|year=1960|pages=184–195|url=http://jmc.stanford.edu/articles/recursive/recursive.pdf|publisher=ACM New York, NY, USA|doi=10.1145/367177.367199}}<br>
{{cite journal|author = John McCarthy||title=Recursive functions of symbolic expressions and their computation by machine, Part I.|journal=Communications of the ACM|volume=3|issue=4|year=1960|pages=184–195|url=http://jmc.stanford.edu/articles/recursive/recursive.pdf|publisher=ACM New York, NY, USA|doi=10.1145/367177.367199}}<br>
{{Cite book | url = http://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf | title = LISP 1.5 Programmer's Manual | publisher = [[MIT Press]] | author = [[John McCarthy]], Paul W. Abrahams, Daniel J. Edwards, Timothy P. Hart, Michael I. Levin | isbn = 0-262-13011-4 | orig-year = 1962 | edition = 2nd | year = 1985 | quote=A function can be simply a name. In this case its meaning must be previously understood. A function may be defined by using the lambda notation and establishing a correspondence between the arguments and the variables used in a form. If the function is recursive, it must be given a name by using a label. ……<br> When a symbol stands for a function, the situation is similar to that in which a symbol stands for an argument. When a function is recursive, it must be given a name. This is done by means of the form LABEL, which pairs the name with the function definition on the a-list. The name is then bound to the function definition, just as a variable is bound to its value.<br>In actual practice, LABEL is seldom used. It is usually more convenient to attach the name to the definition in a uniform manner. This is done by putting on the property list of the name, the symbol EXPR followed by the function definition. The pseudo-function <code>define</code> used at the beginning of this section accomplishes this. When <code>apply</code> interprets a function represented by an atomic symbol, it searches the p-list of the atomic symbol before searching the current a-list. Thus a <code>define</code> will override a LABEL.}}
{{Cite book | url = http://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf | title = LISP 1.5 Programmer's Manual | publisher = [[MIT Press]] | author = [[John McCarthy]], Paul W. Abrahams, Daniel J. Edwards, Timothy P. Hart, Michael I. Levin | isbn = 0-262-13011-4 | orig-year = 1962 | edition = 2nd | year = 1985 | quote=A function can be simply a name. In this case its meaning must be previously understood. A function may be defined by using the lambda notation and establishing a correspondence between the arguments and the variables used in a form. If the function is recursive, it must be given a name by using a label. ……<br> When a symbol stands for a function, the situation is similar to that in which a symbol stands for an argument. When a function is recursive, it must be given a name. This is done by means of the form LABEL, which pairs the name with the function definition on the a-list. The name is then bound to the function definition, just as a variable is bound to its value.<br>In actual practice, LABEL is seldom used. It is usually more convenient to attach the name to the definition in a uniform manner. This is done by putting on the property list of the name, the symbol EXPR followed by the function definition. The pseudo-function <code>define</code> used at the beginning of this section accomplishes this. When <code>apply</code> interprets a function represented by an atomic symbol, it searches the p-list of the atomic symbol before searching the current a-list. Thus a <code>define</code> will override a LABEL.}}
</ref>最开始的LISP是多[[编程范型|范型]]语言,并且随着新的范型的发展,越来越多的编程风格得到了支持。后来发展出来的方言比如[[Scheme]]、[[Clojure]],和分支语言比如[[Dylan (编程语言)|Dylan]]和[[Julia (编程语言)|Julia]]等,试图简化LISP,使它围绕一个函数式核心,而[[Common Lisp]]旨在保留并更新它所替代的各种更早先LISP方言的那些范型特征。<ref>{{cite book |author1=Guy L. Steele |author2=Richard P. Gabriel |title=The Evolution of Lisp |journal=In ACM/SIGPLAN Second History of Programming Languages |pages=233–330 |date=1996-02 |url=http://dreamsongs.com/Files/HOPL2-Uncut.pdf |doi=10.1145/234286.1057818 |isbn=978-0-201-89502-5 |access-date=2019-05-12 |||}}</ref>
</ref>最开始的LISP是多[[编程范型|范型]]语言,并且随着新的范型的发展,越来越多的编程风格得到了支持。后来发展出来的方言比如[[Scheme]]、[[Clojure]],和分支语言比如[[Dylan (编程语言)|Dylan]]和[[Julia (编程语言)|Julia]]等,试图简化LISP,使它围绕一个函数式核心,而[[Common Lisp]]旨在保留并更新它所替代的各种更早先LISP方言的那些范型特征。<ref>{{cite book |author1=Guy L. Steele |author2=Richard P. Gabriel |title=The Evolution of Lisp |journal=In ACM/SIGPLAN Second History of Programming Languages |pages=233–330 |date=1996-02 |url=http://dreamsongs.com/Files/HOPL2-Uncut.pdf |doi=10.1145/234286.1057818 |isbn=978-0-201-89502-5 |access-date=2019-05-12 }}</ref>


而于1956年发明的[[信息处理语言|IPL]]语言,一般被认为是第一个基于计算机的函数式编程语言。<ref>The memoir of Herbert A. Simon (1991), ''Models of My Life'' pp.189-190 {{ISBN|0-465-04640-1}} claims that he, Al Newell, and Cliff Shaw are "...commonly adjudged to be the parents of [the] artificial intelligence [field]," for writing Logic Theorist, a program that proved theorems from ''Principia Mathematica'' automatically. To accomplish this, they had to invent a language and a paradigm that, viewed retrospectively, embeds functional programming.</ref>它是一种用于操纵符号列表的汇编式语言。它有一个生成器的概念,相当于一个接受函数作为参数的函数,并且,由于它是汇编级语言,代码可以是数据,因此IPL可以被视为具有[[高阶函数]]。但是,它在很大程度上依赖于改变列表的结构和类似的指令式编程特征。
而于1956年发明的[[信息处理语言|IPL]]语言,一般被认为是第一个基于计算机的函数式编程语言。<ref>The memoir of Herbert A. Simon (1991), ''Models of My Life'' pp.189-190 {{ISBN|0-465-04640-1}} claims that he, Al Newell, and Cliff Shaw are "...commonly adjudged to be the parents of [the] artificial intelligence [field]," for writing Logic Theorist, a program that proved theorems from ''Principia Mathematica'' automatically. To accomplish this, they had to invent a language and a paradigm that, viewed retrospectively, embeds functional programming.</ref>它是一种用于操纵符号列表的汇编式语言。它有一个生成器的概念,相当于一个接受函数作为参数的函数,并且,由于它是汇编级语言,代码可以是数据,因此IPL可以被视为具有[[高阶函数]]。但是,它在很大程度上依赖于改变列表的结构和类似的指令式编程特征。
第28行: 第28行:
在1960年代早期,[[Kenneth E. Iverson]]开发了[[APL语言|APL]] ,在他1962年出版的《A Programming Language》一书中有所介绍。<ref>{{cite web|author=[[Kenneth E. Iverson]]|title=A Programming Language|url=https://www.jsoftware.com/papers/APL.htm|publisher=Wiley|year=1962}}</ref>APL给John Backus的[[FP (编程语言)|FP]]施加了巨大的影响。在20世纪90年代早期,Iverson和{{en-link|Roger Hui}}创造了[[J语言|J]]语言。在20世纪90年代中期,以前曾与Iverson合作过的{{en-link|Arthur Whitney|Arthur Whitney (computer scientist)|Arthur Whitney}}创建了[[K (编程语言)|K]]语言,后者在金融行业中与其衍生出来的{{en-link|Q (阵列编程语言)|Q (programming language from Kx Systems)|Q}}语言一起被商业化使用。
在1960年代早期,[[Kenneth E. Iverson]]开发了[[APL语言|APL]] ,在他1962年出版的《A Programming Language》一书中有所介绍。<ref>{{cite web|author=[[Kenneth E. Iverson]]|title=A Programming Language|url=https://www.jsoftware.com/papers/APL.htm|publisher=Wiley|year=1962}}</ref>APL给John Backus的[[FP (编程语言)|FP]]施加了巨大的影响。在20世纪90年代早期,Iverson和{{en-link|Roger Hui}}创造了[[J语言|J]]语言。在20世纪90年代中期,以前曾与Iverson合作过的{{en-link|Arthur Whitney|Arthur Whitney (computer scientist)|Arthur Whitney}}创建了[[K (编程语言)|K]]语言,后者在金融行业中与其衍生出来的{{en-link|Q (阵列编程语言)|Q (programming language from Kx Systems)|Q}}语言一起被商业化使用。


1977年[[John Backus]]在他的图灵奖颁奖演讲《编程可以从冯·诺依曼式风格中解放出来吗?一种函数式风格及其程序代数》中,展示了他提出的[[FP (编程语言)|FP]]<ref>{{cite web|url=http://worrydream.com/refs/Backus-CanProgrammingBeLiberated.pdf|title=Can Programming Be Liberated from the von Neumann Style? A Functional Style and Its Algebra of Programs|accessdate=2019-05-12|||}}</ref>。他将函数式编程定义为通过“组合形式”以分层方式构建,允许“程序代数”; 在现代语言中,这意味着函数式程序应遵循[[复合性原理]]。Backus的论文推广了函数式编程的研究,虽然它强调的是[[函数级编程]]而不是现在所说的λ演算风格。
1977年[[John Backus]]在他的图灵奖颁奖演讲《编程可以从冯·诺依曼式风格中解放出来吗?一种函数式风格及其程序代数》中,展示了他提出的[[FP (编程语言)|FP]]<ref>{{cite web|url=http://worrydream.com/refs/Backus-CanProgrammingBeLiberated.pdf|title=Can Programming Be Liberated from the von Neumann Style? A Functional Style and Its Algebra of Programs|accessdate=2019-05-12}}</ref>。他将函数式编程定义为通过“组合形式”以分层方式构建,允许“程序代数”; 在现代语言中,这意味着函数式程序应遵循[[复合性原理]]。Backus的论文推广了函数式编程的研究,虽然它强调的是[[函数级编程]]而不是现在所说的λ演算风格。


1973年[[爱丁堡大学]]的[[Robin Milner]]发明了[[ML语言|ML]]语言,它的语法受到了[[ISWIM]]的启发。同年,{{en-link|David Turner|David Turner (computer scientist)|David Turner}}在[[圣安德鲁斯大学]]开发了[[SASL (编程语言)|SASL]]语言,它基于了[[ISWIM]]的应用式子集<ref>{{cite journal |last=Turner|first=D.A.|title=An Implementation of SASL|journal=University of St. Andrews, Department of Computer Science Technical Report|volume=TR/75/4}}</ref>。在1976年,Turner重新设计并重新实现它为[[惰性求值]]语言<ref>{{cite web|author=D.A. Turner|title=A New Implementation Technique for Applicative Languages|url=https://courses.engr.illinois.edu/cs421/sp2012/project/turner-implementation.pdf}}</ref>。在20世纪70年代的爱丁堡,{{en-link|Rod Burstall}}和John Darlington开发了[[NPL (编程语言)|NPL]]语言。<ref>R.M. Burstall. Design considerations for a functional programming language. Invited paper, Proc. Infotech State of the Art Conf. "The Software Revolution", Copenhagen, 45–57 (1977)</ref>NPL基于[[Stephen Kleene|Kleene]]的[[递归关系|递归方程]],并在他们的程序转换工作中首次引入。<ref>{{cite web|author=R.M. Burstall, J. Darlington|title=A transformation system for developing recursive programs|url=https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.85.645&rep=rep1&type=pdf|publisher=Journal of the Association for Computing Machinery|page= 24(1):44–67|year=1977}}</ref>然后Rod Burstall、David MacQueen和{{en-link|Don Sannella}}结合了来自ML的多态类型检查,从[[NPL (编程语言)|NPL]]派生出了[[Hope (编程语言)|Hope]]语言。<ref>{{cite web|url=https://homepages.inf.ed.ac.uk/dts/pub/hope.pdf|author={{en-link|Rod Burstall}}, D.B. MacQueen, D.T. Sannella. |year=1980|title=Hope: An Experimental Applicative Language}} Conference Record of the 1980 LISP Conference, Stanford University, pp. 136-143.</ref>ML最终发展成几种语言,其中最常见的是[[OCaml]]和[[Standard ML]]。
1973年[[爱丁堡大学]]的[[Robin Milner]]发明了[[ML语言|ML]]语言,它的语法受到了[[ISWIM]]的启发。同年,{{en-link|David Turner|David Turner (computer scientist)|David Turner}}在[[圣安德鲁斯大学]]开发了[[SASL (编程语言)|SASL]]语言,它基于了[[ISWIM]]的应用式子集<ref>{{cite journal |last=Turner|first=D.A.|title=An Implementation of SASL|journal=University of St. Andrews, Department of Computer Science Technical Report|volume=TR/75/4}}</ref>。在1976年,Turner重新设计并重新实现它为[[惰性求值]]语言<ref>{{cite web|author=D.A. Turner|title=A New Implementation Technique for Applicative Languages|url=https://courses.engr.illinois.edu/cs421/sp2012/project/turner-implementation.pdf}}</ref>。在20世纪70年代的爱丁堡,{{en-link|Rod Burstall}}和John Darlington开发了[[NPL (编程语言)|NPL]]语言。<ref>R.M. Burstall. Design considerations for a functional programming language. Invited paper, Proc. Infotech State of the Art Conf. "The Software Revolution", Copenhagen, 45–57 (1977)</ref>NPL基于[[Stephen Kleene|Kleene]]的[[递归关系|递归方程]],并在他们的程序转换工作中首次引入。<ref>{{cite web|author=R.M. Burstall, J. Darlington|title=A transformation system for developing recursive programs|url=https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.85.645&rep=rep1&type=pdf|publisher=Journal of the Association for Computing Machinery|page= 24(1):44–67|year=1977}}</ref>然后Rod Burstall、David MacQueen和{{en-link|Don Sannella}}结合了来自ML的多态类型检查,从[[NPL (编程语言)|NPL]]派生出了[[Hope (编程语言)|Hope]]语言。<ref>{{cite web|url=https://homepages.inf.ed.ac.uk/dts/pub/hope.pdf|author={{en-link|Rod Burstall}}, D.B. MacQueen, D.T. Sannella. |year=1980|title=Hope: An Experimental Applicative Language}} Conference Record of the 1980 LISP Conference, Stanford University, pp. 136-143.</ref>ML最终发展成几种语言,其中最常见的是[[OCaml]]和[[Standard ML]]。
第38行: 第38行:
在1985年{{en-link|David Turner|David Turner (computer scientist)|David Turner}}开发的惰性求值函数式语言[[Miranda (编程语言)|Miranda]]出现,它采用了来自[[ML语言|ML]]与[[Hope (编程语言)|Hope]]语言的概念,作为他先前所设计的[[SASL (编程语言)|SASL]]和[[肯特递归计算器|KRC]]语言的后继者。Miranda对后来的[[Haskell]]有很强的影响,由于它是专有软件,所以Haskell社区于1987年开始达成共识,以形成函数式编程研究的开放标准,对标准的实现自1990年以来一直在进行中。
在1985年{{en-link|David Turner|David Turner (computer scientist)|David Turner}}开发的惰性求值函数式语言[[Miranda (编程语言)|Miranda]]出现,它采用了来自[[ML语言|ML]]与[[Hope (编程语言)|Hope]]语言的概念,作为他先前所设计的[[SASL (编程语言)|SASL]]和[[肯特递归计算器|KRC]]语言的后继者。Miranda对后来的[[Haskell]]有很强的影响,由于它是专有软件,所以Haskell社区于1987年开始达成共识,以形成函数式编程研究的开放标准,对标准的实现自1990年以来一直在进行中。


最近,它在基于CSG几何框架构建的OpenSCAD语言的参数CAD中得到了应用,虽然在重新赋值上的限制(所有值都被当作常量),导致了不熟悉函数式编程的用户混淆。<ref>{{cite web|url = http://forum.openscad.org/Make-discovering-assign-easier-td10964.html|website = OpenSCAD|title = Make discovering assign() easier!|accessdate = 2019-05-12|||}}</ref>
最近,它在基于CSG几何框架构建的OpenSCAD语言的参数CAD中得到了应用,虽然在重新赋值上的限制(所有值都被当作常量),导致了不熟悉函数式编程的用户混淆。<ref>{{cite web|url = http://forum.openscad.org/Make-discovering-assign-easier-td10964.html|website = OpenSCAD|title = Make discovering assign() easier!|accessdate = 2019-05-12}}</ref>


== 应用 ==
== 应用 ==
=== 工业 ===
=== 工业 ===
函数式编程长期以来在学术界流行,但几乎没有工业应用。造成这种局面的主因是函数式编程常被认为严重耗费CPU和记憶体资源<ref>{{cite book|author=Larry C. Paulson|title=ML for the Working Programmer||accessdate=2013-02-10|date=1996-06-28|publisher=Cambridge University Press|isbn=978-0-521-56543-1|||}}</ref><!-- Paulson mentions the reputation for inefficiency in Sec. 1.5; perhaps a more in-depth discussion could be found. -->,这是由于在早期实现函数式编程语言时并沒有考慮过效率问题,而且面向函数式编程特性,如保证{{en-link|参照透明性|Referential transparency}}等,要求独特的数据结构和算法。<ref name='programmingScala'>{{cite book | first1 = Martin | last1 = Odersky | first2 = Lex | last2 = Spoon | first3 = Bill | last3 = Venners | date = 2010-12-13 | title = Programming in Scala: A Comprehensive Step-by-step Guide | publisher = Artima | edition = 2nd | pages = 883/852 | isbn = 978-0-9815316-4-9 | url = http://www.artima.com/shop/programming_in_scala_2ed | access-date = 2019-05-12 | | | }}</ref>
函数式编程长期以来在学术界流行,但几乎没有工业应用。造成这种局面的主因是函数式编程常被认为严重耗费CPU和记憶体资源<ref>{{cite book|author=Larry C. Paulson|title=ML for the Working Programmer||accessdate=2013-02-10|date=1996-06-28|publisher=Cambridge University Press|isbn=978-0-521-56543-1}}</ref><!-- Paulson mentions the reputation for inefficiency in Sec. 1.5; perhaps a more in-depth discussion could be found. -->,这是由于在早期实现函数式编程语言时并沒有考慮过效率问题,而且面向函数式编程特性,如保证{{en-link|参照透明性|Referential transparency}}等,要求独特的数据结构和算法。<ref name='programmingScala'>{{cite book | first1 = Martin | last1 = Odersky | first2 = Lex | last2 = Spoon | first3 = Bill | last3 = Venners | date = 2010-12-13 | title = Programming in Scala: A Comprehensive Step-by-step Guide | publisher = Artima | edition = 2nd | pages = 883/852 | isbn = 978-0-9815316-4-9 | url = http://www.artima.com/shop/programming_in_scala_2ed | access-date = 2019-05-12 }}</ref>


然而,最近几种函数式编程语言已经在商业或工业系统中使用<ref>{{Cite journal|last=Ray|first=Baishakhi|last2=Posnett|first2=Daryl|last3=Devanbu|first3=Premkumar|last4=Filkov|first4=Vladimir|date=2017-09-25|title=A large-scale study of programming languages and code quality in GitHub|url=http://dl.acm.org/citation.cfm?doid=3144574.3126905|journal=Communications of the ACM|language=en|volume=60|issue=10|page=92|doi=10.1145/3126905|via=}}</ref>,例如:
然而,最近几种函数式编程语言已经在商业或工业系统中使用<ref>{{Cite journal|last=Ray|first=Baishakhi|last2=Posnett|first2=Daryl|last3=Devanbu|first3=Premkumar|last4=Filkov|first4=Vladimir|date=2017-09-25|title=A large-scale study of programming languages and code quality in GitHub|url=http://dl.acm.org/citation.cfm?doid=3144574.3126905|journal=Communications of the ACM|language=en|volume=60|issue=10|page=92|doi=10.1145/3126905|via=}}</ref>,例如:
* [[Erlang]],它由瑞典公司[[爱立信]]在20世纪80年代后期开发,最初用于实现容错电信系统。此后,它已在[[北电网络|Nortel]]、[[Facebook]]、[[法国电力公司|Électricité de France]]和[[WhatsApp]]等公司作为流行语言建立一系列应用程序。<ref>{{cite conference | last = Piro | first = Christopher | title = Functional Programming at Facebook | url = http://cufp.galois.com/2009/abstracts.html#ChristopherPiroEugeneLetuchy | year = 2009 | conference = CUFP 2009 | accessdate = 2009-08-29 | | | }}</ref><ref name="whatsapp.blog.2012">[http://blog.whatsapp.com/index.php/2012/01/1-million-is-so-2011/ 1 million is so 2011] // WhatsApp blog, 2012-01-06: "the last important piece of our infrastracture is Erlang"</ref>
* [[Erlang]],它由瑞典公司[[爱立信]]在20世纪80年代后期开发,最初用于实现容错电信系统。此后,它已在[[北电网络|Nortel]]、[[Facebook]]、[[法国电力公司|Électricité de France]]和[[WhatsApp]]等公司作为流行语言建立一系列应用程序。<ref>{{cite conference | last = Piro | first = Christopher | title = Functional Programming at Facebook | url = http://cufp.galois.com/2009/abstracts.html#ChristopherPiroEugeneLetuchy | year = 2009 | conference = CUFP 2009 | accessdate = 2009-08-29 }}</ref><ref name="whatsapp.blog.2012">[http://blog.whatsapp.com/index.php/2012/01/1-million-is-so-2011/ 1 million is so 2011] // WhatsApp blog, 2012-01-06: "the last important piece of our infrastracture is Erlang"</ref>
* [[Scheme]],它被用作早期[[苹果公司|Apple]] [[Macintosh]]计算机上的几个应用程序的基础,并且最近已应用于诸如训练模拟软件和望远镜控制等方向。
* [[Scheme]],它被用作早期[[苹果公司|Apple]] [[Macintosh]]计算机上的几个应用程序的基础,并且最近已应用于诸如训练模拟软件和望远镜控制等方向。
* [[OCaml]],它于20世纪90年代中期推出,已经在金融分析,驱动程序验证,工业机器人编程和嵌入式软件静态分析等领域得到了商业应用。
* [[OCaml]],它于20世纪90年代中期推出,已经在金融分析,驱动程序验证,工业机器人编程和嵌入式软件静态分析等领域得到了商业应用。
* [[Haskell]],它虽然最初是作为一种研究语言,也已被一系列公司应用于航空航天系统,硬件设计和网络编程等领域。
* [[Haskell]],它虽然最初是作为一种研究语言,也已被一系列公司应用于航空航天系统,硬件设计和网络编程等领域。


其他在工业中使用的函数式编程语言包括多范型的[[Scala]]<ref>{{cite conference | last = Momtahan | first = Lee | title = Scala at EDF Trading: Implementing a Domain-Specific Language for Derivative Pricing with Scala | url = http://cufp.galois.com/2009/abstracts.html#LeeMomtahan | year = 2009 | conference = CUFP 2009 | accessdate = 2009-08-29 | | | }}</ref>、[[F#|F#]],还有[[Wolfram语言]]、[[Common Lisp]]、[[Standard ML]]和[[Clojure]]等。
其他在工业中使用的函数式编程语言包括多范型的[[Scala]]<ref>{{cite conference | last = Momtahan | first = Lee | title = Scala at EDF Trading: Implementing a Domain-Specific Language for Derivative Pricing with Scala | url = http://cufp.galois.com/2009/abstracts.html#LeeMomtahan | year = 2009 | conference = CUFP 2009 | accessdate = 2009-08-29 }}</ref>、[[F#|F#]],还有[[Wolfram语言]]、[[Common Lisp]]、[[Standard ML]]和[[Clojure]]等。


=== 教育 ===
=== 教育 ===