您的位置:首页 > 编程语言 > Java开发

Scheme 4 Javaer-3.高阶函数

2015-07-15 14:40 369 查看

1.3 Formulating Abstractions with Higher-Order Procedures

教材有时候按照学生的基础,从0讲起;有时候给出一个大图,然后详细地逐一介绍。

本文或同学们写学习笔记时,要按照后者进行归纳。

函数,是对一些数的复合操作,而且不依赖特定的数。如

(define (cube x) (* x x x))

它不针对某个数如3,而是对所有的参数数据求其立方。由此,它是对

(* 5 5 5)

(* x x x) ; 这里x为实参

的抽象,而(* 5 5 5)等则编写为函数的应用( cube 5)。

注意,函数cube只是将数作为参数。如果能够将函数作为另一个函数的参数,会是一种什么场面呢?

函数是第一阶元素

编程语言通常会对其元素的使用方式,做出一些限制。而受到的限制最少的元素属于第一阶(first-class)。第一阶元素拥有的特权包括:

 用变量命名

 作为函数的参数

 由函数返回

 (可以包含在数据结构中)

Java的基本类型和引用类型,都是第一阶元素。但是,函数在Scheme中如同其基本数据类型一样,完完全全地是第一阶元素

所以,当把函数作为参数、返回值来使用的时候,就有了更高阶的函数。操作函数的函数即为高阶函数

在数学中,序列求和的sigma (∑)记法/符号,就是一个例子。



不管f(x)是什么,高阶函数∑求和。

假定我们有3个具体的求和函数。

1)sum-integers求代数和(从a到b)

(define (sum-integersa b)

(if (> ab)

0

(+ a(sum-integers (+ a 1) b))))

2)sum-cubes求立方和,

3)pi-sum按照公式



求出л/8.

(define (pi-sum a b)

(if (> ab)

0

(+ (/ 1.0 (* a (+ a 2)))(pi-sum (+ a 4) b))))

现在考虑设计一个高阶函数,表达∑符号。显然,除了参数a,b外,还需要指定∑中的项和变化规律,我们以term描述∑中的项,而next描述按照变化规律得到的下一项。则

(define (sum term next a b) ;我喜欢a、b挨着

(if (> ab)

0

(+(term a)

(sumterm next (next a) b))))

定义的sum为∑求和这一高阶函数。

函数作为参数

高阶函数sum中,term和next都是函数形参,类似C的函数指针。假设我们在sum基础上定义求代数和,就需要提供term和next将要绑定的函数。

代数和的term,是一个恒等函数(identity),next是一个自增函数。

(define (identity x) x)

(define (inc n) (+ n 1))

于是,不需要单独定义sum-integers,而是应用高阶函数sum,得到sum-integers

(define (sum-integers a b)

(sum identity inc a b))

(sum-integers 1 10)

另外,对于一次性的小函数,使用lambda表达式非常紧凑。(在这里不是要点)

函数作为返回

高阶函数sum的返回值是一个数,高阶函数强大之处,可以将某些函数作为输入,而又返回一个函数——函数转换。

(define (transf f)

(lambda(a)(+ a (f a)) ) )

(define (square x)

(* x x) )

((transf square) 2)

函数transf的作用是对函数f进行平移,其返回值是由lambda定义的匿名函数。当将匿名函数应用到2时,得到的是2+f(2)。

函数的参数问题

高阶函数transf处理作为参数的函数f时,将它视为只有一个参数的函数,如函数应用(f a)所暗示的。但是作为参数的f,并没有说明这一信息。对于两个参数的op

(define (op x y)

(* x y) )

将它应用到transf中是不应该的。解释器对于(transf op)的输出,为什么不是一个错误?当然,进一步应用会出错。

((transf op) 5) ;要2个参数

((transf op) 1 5) ;要一个参数
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: