FP
全名为(Functional Programming函数式程序设计 )函数式程序设计是一种设计、编制和调试函数式程序的技术。函数式程序是由一些原始函数、定义函数和函数型组成的函数表达式。
Lambda
Lambda Calculus 在数学定义上面非常简单,并且和与图灵机等价,也就是说FP语言程序与普通的命令式语言如C可以写出同样能力的程序。
定义
一个 Lambda 定义就是一个:
lambda <参数> : <函数体>
这个定义可以应用到参数上,进行求值。
例(py):
>>> (lambda x : x + x)(5)
10
Currying
在数学定义中 lambda 只有一个参数,我们可以通过 Currying 来实现组合多个参数的能力:
例:
>>> (lambda x : (lambda y : x + y))(1)(2)
3
这里面所包含的思想是“函数本身也是数据,也是值,可以被传递,可以被计算!",在上面的例子中, "第一个函数接受一个参数并返回另一个接受另一个参数的函数",这听起来有些绕,我们分解来看:
lambda x : 接受一个参数x, 这个定义返回如下的值:
(lambda y: x + y) 这个值是另一个lambda定义,它接受另一个参数y.
Closure
closure在我自己的理解就是表示数据的层次性.
closure我曾经见到有本书翻译成"闭包",封闭(closure),或者叫完全有界(complete bounding)。这里的有界和一阶逻辑谓词中的有界是一个意思.
比如 (lambda x : x + x) , x出现在 lambda x : ....的参数表中, x 就被包含在这个lambda的 context 里面. 再比如前面 currying 的那个例子:
(lambda x : (lambda y : x + y)) y 出现在内层的 lambda 中,它的 context就是内部的那个lambda. 而没有出现在 lambda .. 这里的变量就是自由变量.在这里内部的 lambda y : x + y 中, x 是一个自由变量, y 是有界变量. 在整个 lambda x : ... 的定义中,x,y 都是有界变量.
例:
>>> y = 2
>>> (lambda x : x + y)(4)
6
y 没有出现在 lambda 的参数表中,这里它绑定的是外部context中的 y, 是一个自由变量.
另一个例子:
>>> a = 1
>>> (lambda a : a + 1)(2)
3
当一个 lambda表达式的所有变量都有界时,此表达式才完全合法.
lambda算子计算规则: alpha, beta
alpha 转换
就是说lambda表达式中的参数名称可以随意替换, 名字本身不重要.通过alpha转换可以实现递归等操作.
例:
lambda x, y : x + y
与
lambda a, b : a + b 完全等价.
beta简化
Beta规则无非是说,应用一个函数(也就是lambda表达式。一个意思)等价于通过把函数体内有界的变量替换成应用里对应参数的实际值来替换原来的函数。
例: (lambda x, x + 2) (1) 相当于把 1 替换掉x, 于是得到: 1 + 2
另一个例子:
>>> f = (lambda y : (lambda x : x + y))(5)
>>> f(2)
7
>>> f(1)
6
这里应用一个函数生成了一个 add5 的函数, 动态语言的强大哦, :D
上面的例子,相当于生成了: lambda x : x + 5 这样一个表达式.
再看一个例子:
>>> (lambda x, y : x(y))(lambda x : x * x, 3)
9
>>>
这个例子中, lambda x, y 将x 应用到 y 上. 其中 x 替换成 lambda x : x * x , y 替换成 3.
Beta的严格定义如下:
lambda x . B e = B[x := e] if free(e) /subset free(B[x := e]
这条规则是为了保证出现命名冲突的时候,先进行 alpha 替换,然后再应用 beta 简化.
至此, 通过 lambda , currying, closure, alpha, beta 已经定义出一个"完备"的计算体系. 在此之上,我们可以继续构造出更复杂的程序.