这是代码及其在方案lisp
上的正常工作(define (rdup ls)
(let loop ((ls ls) (current #f))
(cond ((null? ls) ())
((null? (cdr ls)) (if (eq? (car ls) current) () ls))
((eq? (car ls) (cadr ls)) (loop (cdr ls) (car ls)))
((eq? (car ls) current) (loop (cdr ls) current))
(else (cons (car ls) (loop (cdr ls) (car ls)))) )))
这是我试过的
(rdup '(a b a a a c c))
得到(a b)
我想知道代码的每一行是如何工作的
答案 0 :(得分:0)
我添加了行号并修复了缩进以便于解释:
01 (define (rdup ls)
02 (let loop ((ls ls)
03 (current #f))
04 (cond
05 ((null? ls) '())
06 ((null? (cdr ls))
07 (if (eq? (car ls) current) '() ls))
08 ((eq? (car ls) (cadr ls))
09 (loop (cdr ls) (car ls)))
10 ((eq? (car ls) current)
11 (loop (cdr ls) current))
12 (else (cons (car ls)
13 (loop (cdr ls) (car ls)))))))
第02行:您正在使用let语法的特殊形式来创建一个命名过程,然后您可以在let中调用它。您在循环ls
中定义(令人困惑)变量,其名称与循环外部的变量完全相同,为内部变量提供外部变量的初始值。您还要定义第二个参数current
,您将给出初始值#f
。
第04行开始cond
。
第05行(我通过引用空列表进行了更正以使其工作)如果ls
为空,则返回空列表。这将停止该过程并展开堆栈。
第06行检查cdr
是否为空,表示您正在操作列表的最后一个元素。如果确实如此,则转到第07行,如果car
的{{1}}等于ls
,则返回空列表,或者返回current
。这也结束了程序并展开堆栈。
第08-09行连续查找重复项,如果是,则使用ls
作为新列表并将cdr
作为car
来调用循环过程。
第10-11行检查current
是否等于car
,如果是,则调用current
的循环过程(再次向下迭代列表)和{{1} }。
如果没有满足这些条件,则第12-13行将cdr
创建一个新列表 - current
cons
,其结果是调用{{1} car
ls
和let
loop
上创建的cdr
程序。
如果程序按预期工作,则应该返回ls
。
这是一个可以正常运行的程序:
car