帮忙解释一下Scheme中的“cons”是如何工作的?
这是删除列表最后一个元素的函数。
(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 geta 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
cons
构建对,而不是列表。 Lisp 解释器使用“点”在视觉上分隔对中的元素。因此(cons 1 2)
将打印(1 . 2)
。car
和cdr
分别返回一对的第一个和第二个元素。列表是建立在对之上的。如果一对的 cdr 指向另一对,则该序列将被视为列表。最后一对的cdr
将指向一个名为null
的特殊对象(由'()
表示),这告诉解释器它有到达列表末尾。例如,列表'(abc)
是通过计算以下表达式来构造的:list
过程提供了创建列表的快捷方式:表达式
(cons '( abc) '())
创建一个第一个元素是列表的对。您的
remove-dup
过程正在else
子句中创建一对。相反,它应该通过递归调用remove-dup 并将结果作为该对的第二个元素来创建一个列表。我已经稍微清理了该过程:测试:
另请参阅 SICP。
为了完整起见,这里有一个
remove-dup
版本,它删除所有相同的相邻元素: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
andcdr
respectively return the first and second elements of a pair. Lists are built on top of pairs. If thecdr
of a pair points to another pair, that sequence is treated as a list. Thecdr
of the last pair will point to a special object callednull
(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:The
list
procedure provides a shortcut for creating lists:The expression
(cons '(a b c) '())
creates a pair whose first element is a list.Your
remove-dup
procedure is creating a pair at theelse
clause. Instead, it should create a list by recursively callingremove-dup
and putting the result as the second element of the pair. I have cleaned up the procedure a bit:Tests:
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:这里是伪代码:
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.