了解序列的工作原理

Understanding how a sequence works

我有以下 accumulate 功能:

; accumulate
(define (accumulate op initial sequence)
  (if (null? sequence)
      initial
      (op (car sequence) (accumulate op initial (cdr sequence)))))

我正在尝试编写一个 length 函数来使用 accumulate 函数获取序列的长度。

插入accumulate的函数为什么是(+ y 1)而不是(+ x 1)?那是我想不通的部分:

(define (length sequence)
  (accumulate (lambda (x y) (+ x 1)) ; wrong
              0
              sequence))

(define (length sequence)
  (accumulate (lambda (x y) (+ y 1)) ; correct
              0
              sequence))

你的问题是 xy 没有告诉你它是什么。但是,如果您查看 accumulate,您可以看到 op 是如何调用的:

(op (car sequence)                          ; first argument is the element
    (accumulate op initial (cdr sequence))) ; second argument is the accumulated value

虽然它看起来并不是那样 想象一下第二个参数在空序列上调用 accumulate。然后你得到这个:

(op (car sequence)
    initial)

所以让我们length:

(define (length sequence)
  (accumulate (lambda (element initial) 
                ;; initial is often also called acc / accumulator
                (+ 1 initial)) 
              0
              sequence))

所以答案是第一个参数是单个元素,而第二个参数是初始值 (0) 或先前计算的值 01 添加为序列的尾部了。因此一个数字。为什么不使用第一个参数是因为您不能真正使用 "a" 或列表包含的任何内容来计算元素,因为您只需要计算它们而不是将它们用作值。如果您使用第一个参数并且它恰好是字符串什么是 (+ "a" 0) 应该有助于发现列表的长度 1?

如果您将 (lambda (x y) (+ x 1)) 用作 op,那么您的 length(或者更准确地说,accumulate)函数将 不使用 递归调用 accumulate 函数的结果。它基本上只会进行一次计算,(+ x 1),其中 x(car sequence)sequence 的第一个元素——而这个计算 可能或可能甚至没有意义 ,这取决于 x 是否是一个数字,即使它是数字,答案也是错误的。

另一方面,如果 op(lambda (x y) (+ y 1)),那么您的函数将替换

(op (car sequence) (accumulate op initial (cdr sequence)))

(+ (accumulate op initial (cdr sequence)) 1)

递归随着计算(+ 0 1)触底,所以最终得到列表的长度,当每次嵌套递归调用累加return子列表的长度时他们的调用函数。