这是代码,它在 scheme 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)
我想知道每一行代码是如何工作的
最佳答案
我添加了行号并修复了缩进以便于解释:
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
。
如果 ls
为 null,第 05 行(我更正了它,因此它可以通过引用空列表来工作)返回一个空列表。这将停止该过程并展开堆栈。
第 06 行检查 cdr
是否为 null,表明您正在对列表的最后一个元素进行操作。如果是,则转到第 07 行,如果 ls
的 car
等于 current
,则返回一个空列表,或者返回ls
。这也会结束该过程并展开堆栈。
第 08-09 行在一行中查找重复项,如果是,则使用 cdr
作为新列表并使用 car
作为 调用循环过程当前
。
第 10-11 行检查 car
是否等于 current
,如果是,它调用带有 cdr
的循环过程(再次迭代在列表中)和current
。
如果这些条件都不满足,第 12-13 行将通过 cons
创建一个新列表 - 使用 ls
的 car
在 ls
和 car< 的
的 cdr
上调用 let
创建的 loop
过程的结果ls
。
如果程序按预期工作,它应该返回 '(a b c)
。
这是我认为您的程序旨在运行的一个:
(define rdup
(lambda (l)
(reverse (let loop ((lst l)
(c '()))
(cond
((null? lst) c)
(else
(if (member (car lst) c)
(loop (cdr lst) c)
(loop (cdr lst) (cons (car lst) c)))))))))
关于scheme - 我想了解每一行代码如何删除列表中的重复项,所以这是列表 (a b a a c c) 给出的 (a b),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43270332/