高阶函数说明

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 另一个函数而不是计算值。

我的问题是:

  1. 两者之间是否存在显着差异或优缺点? 实施2和实施3?
  2. applyToItself 实现 2 和实现 3 都是高阶函数?
  3. 哪一个是正确的或更好的实现方式?
  1. 差别不大。虽然看到它不是很简单,但版本 2 是柯里化的一种形式,并且返回的过程具有通常不再起作用的变量,因为闭包被 lambda 捕获,只要 squaredouble 存在。

    一些编译器有一种称为 lambda 提升的优化技术,因此一些编译器实际上会将版本 3 重写为版本 2 作为编译过程的一部分,使最终结果相同。

    有时当生成过程的过程进行一些初始化时,比如进行查找,那么这在版本 3 中只会发生一次,而在版本 2 中它会在每个应用程序中进行计算。

  2. v3 具有最多的黑盒,因此具有更好的抽象性,但对于像您展示的简单示例,我经常采用两种方式,而用法并不规定其中一种。有时你需要做 v3。例如。使用 map

  3. 对列表的每个元素求平方

(map (applyToItself * ) '(1 2 3)) ; ==> (1 4 9)