高阶函数说明
Higher Order Function Clarification
刚开始学习函数式编程(使用Scheme语言)。我读到高阶函数是接受另一个函数作为参数或 returns 另一个函数或两者兼而有之的函数。所以我试图将下面的代码转换为高阶函数:
;; define two procedures - one for calculating square & one for finding double of a number
(define (square x) (* x x ))
(define (double x) (+ x x ))
(square 5)
=> 25
(double 5)
=> 10
现在我想出了下面这个:
;; Implementation 2:
(define (applyToItself f x) (f x x ) )
(define (square x) (applyToItself * x ))
(define (double x) (applyToItself + x ))
(square 5)
=> 25
(double 5)
=> 10
我创建了一个函数 applyToItself
,它接受一个函数和一个值,returns 通过对传入值应用传入函数来计算值。
现在 square 和 double 函数只使用 applyToItself
和 * 和 +.
最后我发现了另一种实现方式:
;;Implementation 3:
(define (applyToItself f) (lambda(x) (f x x )) )
(define square (applyToItself * ))
(define double (applyToItself + ))
(square 5)
=> 25
(double 5)
=> 10
这个 applyToItself
实现现在只接受一个函数和 returns 另一个函数而不是计算值。
我的问题是:
- 两者之间是否存在显着差异或优缺点?
实施2和实施3?
- 在
applyToItself
实现 2 和实现 3 都是高阶函数?
- 哪一个是正确的或更好的实现方式?
差别不大。虽然看到它不是很简单,但版本 2 是柯里化的一种形式,并且返回的过程具有通常不再起作用的变量,因为闭包被 lambda 捕获,只要 square
和 double
存在。
一些编译器有一种称为 lambda 提升的优化技术,因此一些编译器实际上会将版本 3 重写为版本 2 作为编译过程的一部分,使最终结果相同。
有时当生成过程的过程进行一些初始化时,比如进行查找,那么这在版本 3 中只会发生一次,而在版本 2 中它会在每个应用程序中进行计算。
是
v3 具有最多的黑盒,因此具有更好的抽象性,但对于像您展示的简单示例,我经常采用两种方式,而用法并不规定其中一种。有时你需要做 v3。例如。使用 map
对列表的每个元素求平方
(map (applyToItself * ) '(1 2 3)) ; ==> (1 4 9)
刚开始学习函数式编程(使用Scheme语言)。我读到高阶函数是接受另一个函数作为参数或 returns 另一个函数或两者兼而有之的函数。所以我试图将下面的代码转换为高阶函数:
;; define two procedures - one for calculating square & one for finding double of a number
(define (square x) (* x x ))
(define (double x) (+ x x ))
(square 5)
=> 25
(double 5)
=> 10
现在我想出了下面这个:
;; Implementation 2:
(define (applyToItself f x) (f x x ) )
(define (square x) (applyToItself * x ))
(define (double x) (applyToItself + x ))
(square 5)
=> 25
(double 5)
=> 10
我创建了一个函数 applyToItself
,它接受一个函数和一个值,returns 通过对传入值应用传入函数来计算值。
现在 square 和 double 函数只使用 applyToItself
和 * 和 +.
最后我发现了另一种实现方式:
;;Implementation 3:
(define (applyToItself f) (lambda(x) (f x x )) )
(define square (applyToItself * ))
(define double (applyToItself + ))
(square 5)
=> 25
(double 5)
=> 10
这个 applyToItself
实现现在只接受一个函数和 returns 另一个函数而不是计算值。
我的问题是:
- 两者之间是否存在显着差异或优缺点? 实施2和实施3?
- 在
applyToItself
实现 2 和实现 3 都是高阶函数? - 哪一个是正确的或更好的实现方式?
差别不大。虽然看到它不是很简单,但版本 2 是柯里化的一种形式,并且返回的过程具有通常不再起作用的变量,因为闭包被 lambda 捕获,只要
square
和double
存在。一些编译器有一种称为 lambda 提升的优化技术,因此一些编译器实际上会将版本 3 重写为版本 2 作为编译过程的一部分,使最终结果相同。
有时当生成过程的过程进行一些初始化时,比如进行查找,那么这在版本 3 中只会发生一次,而在版本 2 中它会在每个应用程序中进行计算。
是
v3 具有最多的黑盒,因此具有更好的抽象性,但对于像您展示的简单示例,我经常采用两种方式,而用法并不规定其中一种。有时你需要做 v3。例如。使用
map
对列表的每个元素求平方
(map (applyToItself * ) '(1 2 3)) ; ==> (1 4 9)