《计算机程序的构造与解释》(四)

高阶抽象

    函数或者过程是一些操作组合的抽象,它代表了某种复合操作,形成某种抽象概念。在定义时形参作为“代词”参与运算。当执行函数调用时,必须指定与函数定义相符的实参,绑定到形参,然后进行运算。

;定义立方运算
(define (cube x)
    (* x x x))
这里的x是形参,其值暂未绑定;当调用cube时(如cube 5),x的值就被绑定为5,然后就是执行(* 5 5 5)运算。还可以定义求平方(square),傅里叶变换(FFT)等等。这样程序员就能在由这些函数概念构造的环境下编程,而不必关心函数的具体实现过程。只要确保每个函数的正确性,那么整个程序的正确性就得到保障。

    但这还不够,所谓高阶函数抽象,是指在某些运算有公共模式,可以运用在不同的函数下。例如求和函数Σf(x)可以对应不同的f(x)。当f(x)=x^2时,就是求平方和,当f(x)=x^3时就是求立方和,诸如此类。这时要定义这个求和函数,它就必须有作为过程的参数。将此过程参数带入函数体,定义整个抽象过程。调用该高阶函数时,也必须传入已定义的过程。

例如求a到b的整数和,其中a<b:a + (a+1) + (a+2) + ... + b

;递归法求整数和
(define (sum_integer a b)
    (if (> a b)
        0
        (+ a (sum_integer (+ a 1) b)))) 
如果求a到b的立方和?

;递归求立方和
(define (sum_cub a b)
    (if (> a b)
        0
        (+ (cube a) (sum_cub (+ a 1) b))))
从这两个计算过程是否能看出有什么模式?对每个元素执行相同的过程,然后计算下一个a值给递归调用,使得递归过程接近base case。

;
(define (<name> a b)
    (if (> a b)
        0
        (+ (<term> a) (<name> (<next> a) b)
其中term和next是已定义的函数,分别计算单个元素的操作和下一个元素的值。

;定义求和的高阶抽象函数
(define (sum term a next b)
    (if (> a b)
        0
        (+ (term a) 
           (sum term (next a) next b)

term是已定义的某个函数,它包含一个参数;a、b指定了term求和的上界和下界限;next表面自变量的步长,如(next a)就是a的下一个值。

用lambda定义过程

    前面讲了简单抽象函数和高阶抽象函数都涉及函数定义。通过define这个特殊规则,在当前环境中(也可以在局部环境中,定义局部过程)将函数名与函数对象绑定,如(define (term x) (<expression>))。实际上它等价于用lambda定义:(define term (lambda (x) (<exprssion>))),也就是将lambda定义的过程绑定为term名称。lambda也可以定义匿名过程,作为高级函数的参数,这样就避免了局部函数的定义。

;lambda定义匿名过程,调用sum高阶函数
(sum (lambda (x) (* x x x))
     a
     (lambda (x) (+ x 1))
     b)
这里利用lambda定义了立方函数(cube)和加一(inc)函数,但是没有命名为cube和inc而是以lambda形式传递给sum高阶函数,完成立方和的运算。

再举一个例子,平均阻尼。

(define (average x y)
    (/  (+ x y) 2))

(define (average-damp f)
    (lambda(x) (average x (f x))))
average-damp有一个函数参数,同时返回一个函数,这个函数接收一个参数,然后返回它与f(x)的平均值。





  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值