我正在阅读SICP并使用Dr Racket SICP软件包作为IDE和解释器。来自SICP的代码:
(define (sum func a next b)
(if (> a b)
0
(+ (func a)
(sum func (next a) next b))))
(define (inc n) (+ n 1))
(define (sum-cubes a b)
(sum cube a inc b))
(define (cube a) (* a a a))
(sum-cubes 1 10)
该函数用于计算1到10之间的立方和。但是我不知道next b
是什么意思,因为我们正在增加a
而不是b,并且增量函数被表示inc
。
所以我删除了next
next b
然后我收到了错误:
define: duplicate argument identifier in: next
我试着抬头"接下来"在语法中却什么也没找到。
不知怎的,我做了这个工作:
(define (sum func a b)
(if (> a b)
0
(+ (func a)
(sum func (inc a) b))))
(define (inc n) (+ n 1))
(define (sum-cubes a b)
(sum cube a b))
(define (cube a) (* a a a))
(sum-cubes 1 10)
但这似乎很奇怪。 func
被cube
取代,所以它非常像C ++中的函数参数?但是怎么不是(func (inc a))
?为什么Scheme会识别func (inc a)
并知道需要将其替换为cube
?
答案 0 :(得分:1)
next
只是一个恰好是函数的参数。它传递了值inc
,因此函数(next a)
中的片段sum
正在计算(inc a)
。以下next b
只是将这些值传递给sum
的递归调用。
<强>加成强>
递归调用只会增加传递给a
的值,并让b
保持原样。递归在a > b
时停止。每个级别func
都会应用于a
并添加到正在累积的值中。 func
是示例中的函数cube
。所以它按照预期对多维数据集求和。
答案 1 :(得分:1)
此表格:
(+ a b)
是3个变量的组合。 +
,a
和b
是变量,Scheme在应用之前以任何顺序对它们进行求值,它接受过程对象和值。
了解用户定义过程中的参数变为变量非常重要。他们可以保留任何值,因此func
和next
只是名称。在代码中,您看到它们正在被应用,例如。它们在操作员位置用括号括起来,这是唯一暗示它们是程序的暗示。也就是说,除了评论中的文档: - )
除了操作员位置之外的其他位置的过程只是传递的值。例如。在(sum func (next a) next b)
中很明显next
是一个过程,它用于生成第二个参数,并且它作为值传递。它在下一次迭代中被绑定到next
,因此它也可以在那里使用。你可以通过使用闭包来避免这种情况:
;;; sums the numbers a ... b
;;; using procedure func as key and
;;; procedure next to compute next value
;;; example:
;;; (sum (λ (v) (* v 2)) ; func
;;; 1 ; a
;;; (λ (v) (+ v 2)) ; next
;;; 10) ; b
;;; => 50
;;; = (+ 2 6 10 14 18)
(define (sum func a next b)
(define (helper a)
(if (> a b)
0
(+ (func a)
(helper (next a)))))
(helper a))
比上面更清楚的方法是使用命名的let
,你也可以引入一个累加器来使这个尾部递归,但我想你最终会在本书后面学到这一点。