纯函数式编程
在电脑科学中,纯函数式编程通常指示一种编程范型,这是建造电脑程序的结构和元素的一种风格,就是将所有计算都当作数学函数的求值(evaluation)。纯函数式编程还可以定义为禁用状态变更和可变数据。
纯与非纯的区别
编辑在纯与非纯函数式编程之间的确切区别是有争议的事情[1]。
当一个程序使用了某些函数式编程概念的时候, 比如头等函数和高阶函数,它通常就被称为是函数式的[2]。但是,头等函数不必然是纯函数式的,由于它可以使用来自指令式范型的技术,比如数组或输入/输出方法,故而它们不是纯函数程序。事实上,最早被引证为函数式的编程语言,IPL和LISP[3][4],按照当前定义都是非纯函数式语言。
纯函数式数据结构必然是持久性数据结构。持久性是函数式编程所要求的,如果没有它,相同的计算就可能返回不同的结果。函数式编程可以使用非纯函数式的持久性数据结构,比如持久性数组,而这些数据结构不可以用在纯函数式程序中。
纯粹采用函数式编程的基础部件(如map、reduce、filter等),进行响应式编程(异步数据流程编程)的编程范型,被称为函数式响应式编程。
纯函数式编程的性质
编辑单赋值
编辑任何改变现存值的赋值(比如x := x + 1
),在纯函数式编程中都是不允许的[5]。在现今的函数式编程中,赋值是被劝阻的,用以支持也叫做“初始化”的单赋值。单赋值是名字绑定的用例,不同于本文其他部分描述的赋值之处在于,它只能做一次,通常是在变量被创建的时候,不允许后续的重新赋值。纯函数式编程共通于数据流程编程的这个特征,简化了并行计算[6],因为求值的两个部分如果都是纯函数式的就会永不交互。
参照透明性
编辑如果将一个表达式替代为它的值只在程序执行的特定点上是有效的,则这个表达式不是参照透明性的。这些顺序点的定义和次序是指令式编程的理论基础。参照透明性的表达式可以在任何时间求值,既不需要定义顺序点也根本不需要对求值次序的任何保证,不需要做这些考虑的编程叫做纯函数式编程。
写参照透明性风格的代码的好处是能得到智慧编译器,易于静态代码分析,和自动进行更好的代码优化。强制参照透明性的语言的主要缺点是,使得表达天然适合指令式编程的步骤序列的运算,更加蠢笨和更不简洁。这些语言通常结合某种机制,使得这些任务更加容易而又保持语言的纯函数式性质,比如明确子句文法和单子。
参照透明性要求表达式是纯函数的,也就是表达式的值对于相同的输入也必须是相同的,它的求值不能有副作用。在现今的函数式编程中,很少使用副作用。缺少副作用导致程序易于形式验证。函数式语言比如Standard ML、Scheme和Scala不限制副作用,但是编程者会习惯性的避免使用它们[7]。函数式语言Haskell使用单子行动来表达副作用,比如输入/输出和其他有状态的计算[8][9]。
数据结构
编辑纯函数式数据结构,是可以用纯函数式语言如Haskell实现的数据结构。实际上,这意味着建造这种数据结构,必须只使用持久性数据类型比如元组、和类型、积类型,和基本类型如整数、字符、字符串。纯函数式数据类型,同它们的指令式对应者相比,经常以不同的方式表现[10]。例如,具有以恒定时间来访问和更新的数组,是多数指令式语言的基本构件,而且很多指令式数据结构,比如散列表和二叉堆,也是基于数组的。数组可以被替代为映射或随机访问列表,它容许纯函数式实现,但是访问和更新时间复杂度是对数。因此,纯函数式数据结构可以用在非纯函数式语言中,但是它们可能不是能得到的最有效率的工具,特别是不要求持久性的情况下。
一般而言,把一个指令式程序转换成纯函数式程序,还需要确保原先可变的那些数据结构,变为显式的传递给并返回自更新它们的函数,这是叫做存储传递风格的一种程序结构。
求值策略
编辑每种求值策略对当纯函数式编程时都返回相同的结果。特别是,它确保编程者不需要考虑程序是按什么次序求值的,因为及早求值(严格求值)将返回同惰性求值(非严格求值)相同的结果。但是,仍有可能一个及早求值可以不终止,而相同程序的惰性求值会停机。纯函数式的好处是惰性求值是可以被更容易的实现,因为所有表达式在任何时刻都返回同样的结果,不用管程序的状态,它们的求值可以随着需要而推延。
纯函数式语言
编辑纯函数式语言是只认可纯函数编程的语言。但是纯函数式程序可以用非纯函数式的语言写成。纯函数式语言主要有:
参见
编辑引用
编辑- ^ Sabry, Amr. What is Purely Functional Language ?. Journal of Functional Programming. January 1993, 8 (1): 1–22. doi:10.1017/S0956796897002943.
- ^ Atencio, Luis. Functional Programming in Javascript. Manning Publications. 18 June 2016. ISBN 978-1617292828.
- ^ 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 which proved theorems from Principia Mathematica automatically. In order to accomplish this, they had to invent a language and a paradigm which, which viewed retrospectively, embeds functional programming.
- ^ McCarthy, John. History of Lisp. In ACM SIGPLAN History of Programming Languages Conference. June 1978: 217–223 [2020-04-24]. doi:10.1145/800025.808387. (原始内容存档于2008-06-07).
- ^ Crossing borders: Explore functional programming with Haskell 互联网档案馆的存档,存档日期November 19, 2010,., by Bruce Tate
- ^ Marlow, Simon. Parallel and Concurrent Programming in Haskell: Techniques for Multicore and Multithreaded Programming. O'Reilly Media. 18 June 2013. ISBN 978-1449335946.
- ^ Matthias Felleisen et al., How To Design Programs, MIT Press. [2021-02-07]. (原始内容存档于2021-05-02).
- ^ Haskell 98 report, http://www.haskell.org (页面存档备份,存于互联网档案馆).
- ^ Imperative Functional Programming, Simon Peyton Jones and Phil Wadler, Conference Record of the 20th Annual ACM Symposium on Principles of Programming Languages, pages 71–84, 1993
- ^ Purely functional data structures (页面存档备份,存于互联网档案馆) by Chris Okasaki, Cambridge University Press, 1998, ISBN 0-521-66350-4