帮忙解释一下Scheme中的“cons”是如何工作的?

发布于 2024-11-02 22:42:42 字数 971 浏览 0 评论 0原文

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

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

因此,根据我的理解,如果我们cons一个列表(例如ab c与一个空列表,即'(),我们应该得到 ab c。然而,在交互窗口(DrScheme)中进行测试,结果是:

If (cons '() '(abc))

(() a b c)

If (cons '(abc) '())

((a b c))

我想搞什么:(! 然后我回到我的问题,删除所有具有相邻重复项的元素。例如, (abaacc) 将是 (ab)

(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 的调用,我看不出哪一部分可以生成这个 .。有什么想法吗?

谢谢,

This is the function that removes the last element of the list.

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

So from my understanding if we cons a list (eg. a b c with an empty list, i.e. '(), we should get
a b c. However, testing in interaction windows (DrScheme), the result was:

If (cons '() '(a b c))

(() a b c)

If (cons '(a b c) '())

((a b c))

I'm like what the heck :(!
Then I came back to my problem, remove all elements which have adjacent duplicate. For example,
(a b a a c c) would be (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))))
        )

  )

It was not correct, however I realize the answer have a . between a b. How could this happen?

`(a . b)`

There was only one call to cons in my code above, I couldn't see which part could generate this .. Any idea?

Thanks,

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

情未る 2024-11-09 22:42:42

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

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

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

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

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

您的 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

为了完整起见,这里有一个 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))

cons build pairs, not lists. Lisp interpreters uses a 'dot' to visually separate the elements in the pair. So (cons 1 2) will print (1 . 2). car and cdr respectively return the first and second elements of a pair. Lists are built on top of pairs. If the cdr of a pair points to another pair, that sequence is treated as a list. The cdr of the last pair will point to a special object called null (represented by '()) and this tells the interpreter that it has reached the end of the list. For example, the list '(a b c) is constructed by evaluating the following expression:

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

The list procedure provides a shortcut for creating lists:

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

The expression (cons '(a b c) '()) creates a pair whose first element is a list.

Your remove-dup procedure is creating a pair at the else clause. Instead, it should create a list by recursively calling remove-dup and putting the result as the second element of the pair. I have cleaned up the procedure a bit:

(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))

Tests:

> (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)

Also see section 2.2 (Hierarchical Data and the Closure Property) in SICP.

For completeness, here is a version of remove-dup that removes all identical adjacent elements:

(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))
痴梦一场 2024-11-09 22:42:42

这里是伪代码:

class Pair {
物体离开,
对象正确}。

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

所以,
1. cons('A,'B) =>;对('A,'B)
2. cons('A,NIL) =>;对('A,NIL)
3. cons(NIL,'A) =>;对(NIL,'A)
4. cons('A,cons('B,NIL)) =>对('A,对('B,NIL))
5. cons(cons('A 'B),NIL)) => Pair(Pair('A,'B),NIL)

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

希望,你明白了。

关于你的职能。您正在处理“列表”,但构建“对”。
列表是成对的,但并非所有对都是列表!要成为列表对,必须以 NIL 作为尾部。

(ab) 配对 &列表
(a . b) 对未列出

尽管有缺点,但您的函数有错误,它只是不适用于 '(abaaccd)。由于这与您的问题无关,我不会在这里发布修复程序。

Here in pseudocode:

class Pair {
Object left,
Object right}.

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

So,
1. cons('A,'B) => Pair('A,'B)
2. cons('A,NIL) => Pair('A,NIL)
3. cons(NIL,'A) => Pair(NIL,'A)
4. cons('A,cons('B,NIL)) => Pair('A, Pair('B,NIL))
5. cons(cons('A 'B),NIL)) => Pair(Pair('A,'B),NIL)

Let's see lefts and rights in all cases:
1. 'A and 'B are atoms, and whole Pair is not a list, so (const 'a 'b) gives (a . b) in scheme
2. NIL is an empty list and 'A is an atom, (cons 'a '()) gives list (a)
3. NIL and 'A as above, but as left is list(!), (cons '() 'a) gives pair (() . a)
4. Easy case, we have proper list here (a b).
5. Proper list, head is pair (a . b), tail is empty.

Hope, you got the idea.

Regarding your function. You working on LIST but construct PAIRS.
Lists are pairs (of pairs), but not all pairs are lists! To be list pair have to have NIL as tail.

(a b) pair & list
(a . b) pair not list

Despite cons, your function has errors, it just don't work on '(a b a a c c d). As this is not related to your question, I will not post fix for this here.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文