帮助解释Scheme中的“cons”如何工作?

时间:2011-04-21 07:49:20

标签: scheme

这是删除列表最后一个元素的函数。

(define (remove-last ll)
  (if (null? (cdr ll))
      '()
      (cons (car ll) (remove-last (cdr ll)))))

根据我的理解,如果我们cons列出一个列表(例如带有空列表的a b c,即'(),我们应该得到 a b c。但是,在交互窗口(DrScheme)中进行测试,结果是:

如果(cons'()'(a b c))

(() a b c)

如果(cons'(a b c)'())

((a b c))

我喜欢哎呀:(! 然后我回到我的问题,删除所有具有相邻副本的元素。例如, (a b a a c c)将是(a b)

(define (remove-dup lst)
  (cond ((null? lst) '())
        ((null? (cdr lst)) (car lst))
        ((equal? (car lst) (car (cdr lst))) (remove-dup (cdr (cdr lst))))
        (else (cons (car lst) (car (cdr lst))))
        )

  )

这不正确,但我发现答案在.之间有a b。怎么会发生这种情况?

`(a . b)`

上面的代码中只有一次调用cons,我无法看到哪个部分可以生成此.。有什么想法吗?

谢谢,

2 个答案:

答案 0 :(得分:27)

cons构建对,而不是列表。 Lisp解释器使用“点”来直观地分离对中的元素。因此(cons 1 2)将打印(1 . 2)carcdr分别返回一对的第一个和第二个元素。列表建立在对之上。如果一对中的cdr指向另一对,则将该序列视为列表。最后一对的cdr将指向一个名为null的特殊对象(由'()表示),这告诉解释器它已到达列表的末尾。例如,列表'(a b c)是通过计算以下表达式构建的:

> (cons 'a (cons 'b (cons 'c '())))
(a b c)

list程序提供了创建列表的快捷方式:

> (list 'a 'b c)
(a b c)

表达式(cons '(a b c) ())创建一对第一个元素是列表的对。

您的remove-dup程序正在else子句创建一对。相反,它应该通过递归调用remove-dup并将结果作为该对的第二个元素来创建列表。我已经清理了一下程序:

(define (remove-dup lst)
  (if (>= (length lst) 2)
      (if (eq? (car lst) (cadr lst))
          (cons (car lst) (remove-dup (cddr lst)))
          (cons (car lst) (remove-dup (cdr lst))))
      lst))

试验:

> (remove-dup '(a b c))
(a b c)
> (remove-dup '(a a b c))
(a b c)
> (remove-dup '(a a b b c c))
(a b c)

另见SICP中的2.2节(分层数据和关闭属性)。

为了完整性,这里有remove-dup版本,删除所有相同的相邻元素:

(define (remove-dup lst)
  (if (>= (length lst) 2)
      (let loop ((f (car lst)) (r (cdr lst)))
        (cond ((and (not (null? r))(eq? f (car r)))
               (loop f (cdr r)))               
              (else
               (cons (car lst) (remove-dup r)))))
      lst))

答案 1 :(得分:1)

这里是伪代码:

班对{  物件离开了,  对象权限}。

function cons(Object left,Object right){return new Pair(left,right)};

所以, 1. cons('A,'B)=>一对( 'A,' B) 2. cons('A,NIL)=>一对('A,NIL) 3.缺点(NIL,'A)=>对(NIL,'A) 4. cons('A,cons('B,NIL))=>配对('A,配对('B,NIL)) 5.缺点(cons('A'B),NIL))=>对(对( 'A,' B),NIL)

让我们看看所有情况下的左派和权利: 1.'A和'B是原子,整个Pair不是列表,所以(const'a'b)给出(a.b)in scheme 2. NIL是一个空列表,'A是原子,(cons'a'())给出列表(a) 3. NIL和'A如上,但左边是列表(!),(cons'()'a)给对(()。a) 4.简单的情况,我们在这里有适当的列表(a b)。 5.正确的清单,头是对(a.b),尾是空的。

希望,你明白了。

关于你的功能。您正在进行LIST但是构建了PAIRS。 列表是对(成对),但不是所有对都是列表!列表对必须有NIL作为尾部。

(a b)对&名单 (a.b)配对不列出

尽管有缺点,但是你的功能有错误,它只是不起作用'(a b a a c c d)。由于这与您的问题无关,我不会在此处发布修复。