对于应用程序员,需要知道的是:函数编程语言把函数视为数据。
换言之,编程语言中的一切元素,归根结底都是λ表达式;正如命令思维的人认为的:编程语言中的一切元素,归根结底都是0和1.
但是对于程序员(语言使用者),我们了解了“归根结底”之后,真正需要知道的是:函数是数据。(而不是相反,数据也是λ表达式)。
“数据意味着什么?”我不知道作者为什么这样写。我认为,如果是寻根之旅,就应该明确说明:本节的中心思想是“归根结底”。
通常,我会将这一部分的内容放在最开始的引言中介绍。参考《编程导论(Java)·1.4.3函数式编程范式》
yqj2065个人认为,练习2.6是SICP整本书中最重要的一个练习题。
丘奇数(Church numeral),并不是一个数字,而是指应用某个函数的次数。高阶函数Church- zero有两个参数f和x,表示丘奇数0,即函数f应用0次。同理可得丘奇数1和丘奇数2。
(define Church-zero (lambda (f) (lambda (x) x)))
(define Church-one (lambda (f) (lambda (x) (f x)))) ;;;应用1次f (define Church-two (lambda (f) (lambda (x) (f (f x))))) ;;;应用2次f假设有求平方的函数square(这里假设——当然Scheme也已经定义了乘法操作符*)。
(define (squarex) (* x x))
应用函数Church-two,其参数为square和3(这里假设已经定义了数字3)
((Church-two square) 3) →81
当对参数3应用两次求平方函数square,结果为81。【附:练习2.6中要求通过代换求(add-1 zero)的值的方式,给出丘奇数1和丘奇数2(不得直接使用add-1和 zero)。已知add-1
(define (add-1 n)
(lambda (f) (lambda (x) (f ((n f) x)))))
先看看代换规律:例如
(define add (lambda (x y) (+ x y)))
(add 1 2 )→(+ 1 2) ;;;β简化
所以(注lambda (f)写成λf,使用α-变换和β简化)
Church-one = (++ Church-zero)
=> (λn.λf.λx.(f ((n f) x)) Church-zero)
=> λf.λx.(f ((Church-zero f) x));;; β简化。
=> λf.λx.(f ((λg.λy.y f) x));;α-变换,避免混淆
=>λf.λx.(f (λy.y x)) ;;; β简化
=>λf.λx.(f x) ;;; β简化
最后得:(define one (lambda (f) (lambda (x) (f x)))) 】
为了定义数字zero、one、two……,首先需要定义一个自增函数++(SICP上的add-1),其参数有3个。其中n是一个丘奇数。
(define (++ n)(lambda (f)(lambda (x) (f ((n f) x)))))
从Church-zero和++,可以简单地定义Church-one:
(define Church-one (++ Church-zero))
也可以通过代换的方式求(++zero)的值,给出丘奇数1和丘奇数2的直接定义。
但是,单纯地通过丘奇的λ演算——即不使用任何Scheme已经定义的东西,定义数字zero难度太大。所以,借用Scheme已经定义的数字1和+,自增函数++为:
(define ++ (lambda (x) (+ x 1)))
在这个投机取巧的自增函数++基础上(借用Scheme已经定义的数字0),我们得到数字my0、my1、my2的定义:
(define my0 ((Church-zero ++) 0))
(* 2 my0)
(define my1 ((Church-one ++) 0))
(* 2 my1)
(define my2 ((Church-two ++) 0))
根据++函数,丘奇数m+n的+函数定义为:
+ = λm.λn.λf.λx.((((m ++) n) f) x)
验证如下:求丘奇数2+1
((+ Church-two) Church-one) = ((λm.λn.λf.λx.((((m++) n) f) x) Church-two) Church-one)
=> (λn.λf.λx.(((( Church-two ++)n) f) x)Church-one);;; β简化,替换m
=>λf.λx.(((( Church-two ++) Church-one) f) x) ;;; β简化,替换n
=>λf.λx.(( ( ( λg.λy.(g (g y)) ++) Church-one) f) x) ;; 展开与α-变换
=>λf.λx.((( λy.(++ (++ y)) Church-one) f) x)
=>λf.λx.(( (++ (++ Church-one) ) f) x) ;; 已知(++ Church-one)= Church-two
=>λf.λx.(( ( ++ Church-two ) f) x) ;; 展开++
=>λf.λx.(( ( λn.λg.λy.(g ((n g) y)) Church-two ) f) x)
=>λf.λx.(( λg.λy. (g ((Church-two g) y)) f) x)
=> λf.λx.(( λg.λy.(g ( (λh.λz.(h (h z)) g) y)) f) x)
=>λf.λx.(( λg.λy.(g (λz.(g(g z)) y) ) f) x)
=>λf.λx.( (λg.λy.(g (g (g y))) f) x)
=>λf.λx.( λy.(f (f (f y))) x)
=>λf.λx.(f (f (f x)))