1.3 用高阶函数做抽象
1.3.1 过程作为参数
1.高阶过程
以过程作为参数,或者以过程作为返回值,这类能操作过程的过程称之为高阶过程。
2.应用于积分
模式一:
(define (sum term a next b)
(if (> a b)
0
(+ (term a)
(sum term (next a) next b))))
计算:其中,f = x³ ,a=0;b=1
(define (integral1 f a b dx)
(define (add-dx x) (+ x dx))
(* (sum f (+ a (/ dx 2.0)) add-dx b)
dx))
(define (cube x) (* x x x))
(integral1 cube 0 1 0.01)
>0.24998750000000042 ;;cube在0和1间积分的精确值是1/4
此方法计算积分并不准确,是一个近似值。练习1.29会给出一个更精确的求积分的方法:辛普森规则。
这种函数不能应用于其他语言,1.3.2节说明如和摆脱这种定义
1.3.2 用lambda构造过程
1. 一般形式
(lambda (<formal-parameters>) <body>)
<formal-parameters>为形式参数;<body>为过程体
lambda用于define同样的方式创建过程,此过程不与环境中任何名字相关联。
按如下方式阅读lambda表达式:
(lambda (x) ( + x 4))
该过程 以x为参数 它加起 x 和 4
2.lambda的应用
1.不需要定义辅助过程
(define (pi-sum a b)
(sum (lambda (x) (/ 1.0 (* x (+ x 2)))) ;;sum的定义是上面的模式一
a
(lambda (x) (+ x 4))
b))
2.可用作组合式的运算符
((lambda (x y z) (+ x y (* z z))) 1 2 3)
3.用let创建局部变量
1. 一般形式
(let ((<var1> <exp1>)
(<var2> <exp2>)
:
(<varn> <expn>))
<body>)
可以将它读作
令 <var1> 具有值 <exp1> 而且
<var2> 具有值 <exp2> 而且
:
<varn> 具有值 <expn>
:
在 <body>中
2.let表达式被解释为替代如下表达式的另一种语法形式
(对比 lambda可用作组合式的运算符 容易懂)
((lambda (<var1> ...<varn>)
<body>)
<exp1>
:
<expn>)
let表达式只是作为基础的lambda表达式的语法外衣罢了
1. 用于与注意
1).let使人能在尽可能接近其使用的地方创建局部变量约束:
(define (test x)
(+ x (let ((x 6)) (- x 2))))
(test 6)
>10
2).变量的值是在let之外计算的
(define (test x)
(let ((x 3)
(y (+ x 2)))
(* x y)))
(test 2)
>12
1.3.3 过程作为一般性方法
目的: 如何通过过程去直接描述这些方法
1.通过区间折半寻找方程的根
(define (average x y) (/ (+ x y) 2)) ;求两个数平均值
(define (close-enough? x y) ;;两数之差的绝对值是否足够接近0.001
(< (abs (- x y)) 0.001))
#|检测过程|#
(define (search f neg-point pos-point)
(let ((midpoint (average neg-point pos-point)))
(if (close-enough? neg-point pos-point)
midpoint
(let ((te