SCHEME程序说明

SCHEME program explanation

正在备考,这是一道练习题:

What does the following Scheme function do? You must explain each block/case of the codes and provide two test cases.

(define (x lis)
 (cond
   ((null? lis) 0)
   ((not (list? (car lis)))
    (cond
      ((eqv? (car lis) 3)(x (cdr lis)))
      (else (+ 1 (x (cdr lis))))))
   (else (+ (x (car lis)) (x (cdr lis))))
 )
)

有人可以分解这段代码吗?

首先,我将这段代码重写为更易读的形式(我还将内部cond替换为if,代码的含义不会改变):

(define (x lis)
  (cond
    ((null? lis) 0)
    ((not (list? (car lis)))
     (if
      (eqv? (car lis) 3)
      (x (cdr lis))
      (+ 1 (x (cdr lis)))))
    (else (+ (x (car lis))
             (x (cdr lis))))))

现在,我将逐行打破这一点:

  • cond 包含三个子句 null?list? (car ...)else - 你正在遍历给定的列表,对每个元素做一些事情
  • ((null? lis) 0): 零是加法的中性元素,所以这个函数的结果将是数字,你在求和
  • ((not (list? (car lis))):当 car 是“原子”时...
  • (eqv? (car lis) 3)
  • ... 它是 3,用 (cdr lis) 调用这个函数 = 忽略这个元素
  • ...而且它不是 3,用 (cdr lis) 调用这个函数,但是将 1 添加到结果
  • (+ (x (car lis)) (x (cdr lis))) else 将在 car 上调用的此函数的结果与在 cdr 上调用的此函数的结果相加(这是函数的常见模式,它使用嵌套列表,例如示例 flatten)

那么,这个函数有什么作用呢?它 returns 给定列表中不同于 3 的元素数,并且给定列表可以嵌套。

查看示例:

> (x '(1 2 3 4 5))
4

列表中有五个元素,但有一个是eqv?3,所以你不要算。

> (x '(3 3 3))
0

列表中的三个元素,但每个元素都是 eqv?3,因此您将它们全部跳过。

> (x '(1 2 (3 4) (5 6 (7))))
6

这个嵌套列表中有七个元素,但是一个是 eqv?3,所以你只数了六个。