解决推迟操作的问题的方法是以不推迟操作的方式编写代码13。这需要编写一个不同的模式,通常涉及编写两个函数定义,一个初始化函数和一个辅助函数。
初始化函数设置任务;辅助函数执行工作。
以下是两个求和的函数定义。它们非常简单,我发现它们很难理解。
(defun triangle-initialization (number) "返回从1加到NUMBER(包括)的数字的和。 这是使用递归的两个函数对的初始化组件。" (triangle-recursive-helper 0 0 number))
(defun triangle-recursive-helper (sum counter number) "使用COUNTER返回SUM,通过NUMBER(包括)。 这是使用递归的两个函数对的辅助组件。" (if (> counter number) sum (triangle-recursive-helper (+ sum counter) ; sum (1+ counter) ; counter number))) ; number
通过评估这两个函数定义来安装它们,然后使用2行调用triangle-initialization
:
(triangle-initialization 2) ⇒ 3
初始化函数使用三个参数调用辅助函数的第一个实例:零,零,以及三角形中的行数。
传递给辅助函数的前两个参数是初始化值。这些值在triangle-recursive-helper
调用新实例时会更改。14
让我们看看当我们有一个只有一行的三角形时会发生什么。(这个三角形将有一个小石子!)
triangle-initialization
将使用参数0 0 1
调用它的辅助函数。该函数将运行条件测试,即(> counter number)
:
(> 0 1)
并发现结果为假,因此它将调用if
子句的else部分:
(triangle-recursive-helper (+ sum counter) ; sum加counter ⇒ sum (1+ counter) ; 增加counter ⇒ counter number) ; number保持不变
这将首先计算:
(triangle-recursive-helper (+ 0 0) ; sum (1+ 0) ; counter 1) ; number
即:
(triangle-recursive-helper 0 1 1)
再次,(> counter number)
将为假,因此Lisp解释器将评估triangle-recursive-helper
,创建一个新实例并传递新参数。
这个新实例将是:
(triangle-recursive-helper (+ sum counter) ; sum加counter ⇒ sum (1+ counter) ; 增加counter ⇒ counter number) ; number保持不变
即:
(triangle-recursive-helper 1 2 1)
在这种情况下,(> counter number)
测试将为真!因此,该实例将返回sum
的值,该值将是1,符合预期。
现在,让我们将triangle-initialization
的参数设置为2,以查看具有两行的三角形中有多少个小石子。
该函数调用(triangle-recursive-helper 0 0 2)
。
分阶段,被调用的实例将是:
sum counter number
(triangle-recursive-helper 0 1 2)
(triangle-recursive-helper 1 2 2)
(triangle-recursive-helper 3 3 2)
当调用最后一个实例时,(> counter number)
测试将为真,因此该实例将返回sum
的值,该值将是3。
这种模式在编写可能使用计算机中的许多资源的函数时很有帮助。