[emacs lisp]求解cons和list的差别?

41 views
Skip to first unread message

池塘仙人

unread,
Feb 27, 2012, 6:06:02 AM2/27/12
to Lisp-cn(Lisp中文用户组)
;这是一个二叉树的插入功能
(progn
(defun create-node(x)
(list x nil nil)
)
;这里这个create-node运行正常,但是如果使用(cons x '(nil nil))就不行,为什么呢?
(defun get-left (node)
(cdr node)
)

(defun get-right (node)
(cdr (cdr node))
)

(defun insert-left-nil (node x)
(setcar (get-left node) (create-node x))
)

(defun insert-right-nil (node x)
(setcar (get-right node) (create-node x))
)

(defun find-parent (tree x)
(let ((child t) (node tree) parent)
(while (and child node)
(if (= x (car node))
(setq child nil)
(progn
(setq parent node)
(if (< x (car node))
(setq node (car (get-left node)))
(setq node (car (get-right node)))
)
)
)
)
(and child parent)
)
)

(defun insert(tree x)
(if (not tree)
(create-node x)
(let ((temp (copy-alist tree)) parent)
(if (setq parent (find-parent temp x))
(if (< x (car parent))
(insert-left-nil parent x)
(insert-right-nil parent x)
)
)
(setq temp temp)
)
)
)

(defun inserts (tree list)
(let ((temp (copy-alist tree)) (last (copy-alist list)))
(while last
(setq temp (insert temp (car last)))
(setq last (cdr last))
)
(and t temp)
)
)
)

Nala Ginrut

unread,
Feb 27, 2012, 7:53:20 AM2/27/12
to lis...@googlegroups.com


2012/2/27 池塘仙人 <yourna...@gmail.com>

;这是一个二叉树的插入功能
(progn
 (defun create-node(x)
   (list x nil nil)
   )
;这里这个create-node运行正常,但是如果使用(cons x '(nil nil))就不行,为什么呢?

nil ==> #nil
'nil ==> (quote nil)
 

--
Lisp-cn(Lisp中文用户组)
CLUG http://lisp.org.cn

池塘仙人

unread,
Feb 27, 2012, 8:38:23 AM2/27/12
to Lisp-cn(Lisp中文用户组)
奇怪,我的标题有写是emacs lisp怎么变没了
这里没有'nil,'(nil nil)里的nil仍然是nil(或许我理解不对?)
单独的(list x nil nil)和(cons x '(nil nil))没有差别(从打印结果看),当放在这个二叉树里,树的层数到3的时候
(cons x '(nil nil))才出问题,不解

On Feb 27, 8:53 pm, Nala Ginrut <nalagin...@gmail.com> wrote:
> 2012/2/27 池塘仙人 <yourname1...@gmail.com>

Nala Ginrut

unread,
Feb 27, 2012, 9:04:24 AM2/27/12
to lis...@googlegroups.com


2012/2/27 池塘仙人 <yourna...@gmail.com>

奇怪,我的标题有写是emacs lisp怎么变没了
这里没有'nil,'(nil nil)里的nil仍然是nil(或许我理解不对?)
单独的(list x nil nil)和(cons x '(nil nil))没有差别(从打印结果看),当放在这个二叉树里,树的层数到3的时候
(cons x '(nil nil))才出问题,不解

试过了不行?
 

池塘仙人

unread,
Feb 27, 2012, 9:18:01 AM2/27/12
to Lisp-cn(Lisp中文用户组)
一个简单的测试是
(insert (insert (insert nil 7) 6) 5)

当使用(cons x '(nil nil))的时候
运行结果是
(7 (6 (5 #2 nil) nil) nil)
再次运行结果竟然还变成
(7 (5 (5 #2 (6 #2 #3)) (6 (5 #3 #2) #2)) nil)
继续运行竟然会一直变

当使用(list x nil nil)的是
运行结果就是
(7 (6 (5 nil nil) nil) nil)
很正常,重复运行也不会出问题

Nala Ginrut

unread,
Feb 27, 2012, 9:34:35 AM2/27/12
to lis...@googlegroups.com


2012/2/27 池塘仙人 <yourna...@gmail.com>

一个简单的测试是
(insert (insert (insert nil 7) 6) 5)

当使用(cons x '(nil nil))的时候
运行结果是
(7 (6 (5 #2 nil) nil) nil)
再次运行结果竟然还变成
(7 (5 (5 #2 (6 #2 #3)) (6 (5 #3 #2) #2)) nil)
继续运行竟然会一直变

当使用(list x nil nil)的是
运行结果就是
(7 (6 (5 nil nil) nil) nil)
很正常,重复运行也不会出问题


是叫你试quansiquote: (cons `(,nil ,nil))
 'nil ==> (quote nil) ==> 普通符号nil
  nil ==> #nil ==> 特殊符号nil
对特殊符号的parse随实现而不同,标准只保证语法定义,不能保证所有特殊符号一定不解释成普通符号

池塘仙人

unread,
Feb 27, 2012, 9:51:43 AM2/27/12
to Lisp-cn(Lisp中文用户组)
你是说
(cons '(,nil ,nil))
还是(cons '('nil 'nil))
不过我两个都试了都不行

Nala Ginrut

unread,
Feb 27, 2012, 9:55:20 AM2/27/12
to lis...@googlegroups.com


2012/2/27 池塘仙人 <yourna...@gmail.com>

你是说
(cons '(,nil ,nil))
还是(cons '('nil 'nil))
不过我两个都试了都不行


(cons x `(,nil ,nil))
是`不是',1左边那个
 

池塘仙人

unread,
Feb 27, 2012, 10:15:01 AM2/27/12
to Lisp-cn(Lisp中文用户组)
哦,可以了,以前没见过这种写法--,那list为什么不用这种写法也可以呢?

Nala Ginrut

unread,
Feb 27, 2012, 10:18:12 AM2/27/12
to lis...@googlegroups.com


2012/2/27 池塘仙人 <yourna...@gmail.com>
哦,可以了,以前没见过这种写法--,那list为什么不用这种写法也可以呢?


你需要了解下quote、unquote、quansiquote以及unquote-splicing的区别和用法。
实在搞不清楚再问。
 
Message has been deleted

oni...@gmail.com

unread,
Feb 27, 2012, 9:08:34 PM2/27/12
to Lisp-cn(Lisp中文用户组)
(list x nil nil) => (cons x (cons nil (cons nil nil)))

(cons x '(nil nil)) => (cons x (quote nil nil)) => (cons x (list
(quote nil) (quote nil))) => (cons x (cons (quote nil) (cons (quote
nil) nil)))

But (cons x (cons nil (cons nil nil))) can't be (cons x (cons (quote
nil) (cons (quote nil) nil)))

So they are different.

BTW, don't use `(,nil ,nil) to do this though it solves your problem.

Liu Cheng

unread,
Feb 27, 2012, 10:04:53 PM2/27/12
to lis...@googlegroups.com
(cons x '(nil nil)) 应该是 (cons x (quote (nil nil))吧- -

2012/2/28 oni...@gmail.com <oni...@gmail.com>:

Nala Ginrut

unread,
Feb 27, 2012, 10:11:46 PM2/27/12
to lis...@googlegroups.com



(list x nil nil) => (cons x (cons nil (cons nil nil)))

(cons x '(nil nil)) => (cons x (quote nil nil)) => (cons x (list
(quote nil) (quote nil))) => (cons x (cons (quote nil) (cons (quote
nil) nil)))

But (cons x (cons nil (cons nil nil))) can't be  (cons x (cons (quote
nil) (cons (quote nil) nil)))


如果你看懂我之前的解答,就不需要补充这一点了。
 
So they are different.

BTW, don't use `(,nil ,nil) to do this though it solves your problem.


没什么不可以用的,只是用这种方式告诉他#nil和(quote nil)是不同的。

 

oni...@gmail.com

unread,
Feb 28, 2012, 12:15:47 AM2/28/12
to Lisp-cn(Lisp中文用户组)
You are right. Thanks for pointing it out.

oni...@gmail.com

unread,
Feb 28, 2012, 12:51:38 AM2/28/12
to Lisp-cn(Lisp中文用户组)
Sorry to piss you off. Any way,

> > (list x nil nil) => (cons x (cons nil (cons nil nil)))
>
> > (cons x '(nil nil)) => (cons x (quote nil nil)) => (cons x (list
> > (quote nil) (quote nil))) => (cons x (cons (quote nil) (cons (quote
> > nil) nil)))
>
> > But (cons x (cons nil (cons nil nil))) can't be (cons x (cons (quote
> > nil) (cons (quote nil) nil)))
>
> 如果你看懂我之前的解答,就不需要补充这一点了。

To expand the forms, you get clear explanation.
Excuse me for the typo, if you will. :)

Liu Cheng

unread,
Feb 28, 2012, 1:01:45 AM2/28/12
to lis...@googlegroups.com
我来解释下吧:
(cons key '(nil nil))

(list key nil nil) 的结果都是 (key nil nil) 这是没错的
不过如果你调用两次(cons key '(nil nil))时,它们指向了同一个(nil nil)的pair,这样你修改其中一个的时候,另一个会意外的改变。
你执行下以下代码,再检查下a b的值就明白了
(defun create-node(key)
(cons key '(nil nil)))

(setq a (create-node 1))
(setq b (create-node 2))

(setcar (cdr a) 1)

2012/2/28 oni...@gmail.com <oni...@gmail.com>:

oni...@gmail.com

unread,
Feb 28, 2012, 2:32:49 AM2/28/12
to Lisp-cn(Lisp中文用户组)
I think you have the truth. Actually my previous replies seems
untenable. (My bad, just curse me!)
I found there are some comments, and I think it may also apply to
ELisp.

The difference is not because of quoted nil, it is because that
compiler may coalesce the quoted forms since it thinks the forms are
constant literals.

Here is what I found the explanation of the answer:
====================================
(defun should-be-constant ()
'(one two three))

(let ((stuff (should-be-constant)))
(setf (third stuff) 'bizarre)) ; bad!

(should-be-constant) ; returns (one two bizarre)

Modifying a quoted form like this is generally considered bad style,
and is defined by ANSI Common Lisp as erroneous (resulting in
"undefined" behavior in compiled files, because the file-compiler can
coalesce similar constants, put them in write-protected memory, etc.).

Reference from:
http://en.wikipedia.org/wiki/Lisp_(programming_language)

------------------------------------------------------
For example, the compiler is allowed
to coalesce constants including literals:

(let ((a '(1 2 3))
(b '(1 2 3)))
(eq a b)) ; => T or NIL

The upshot of which is that modifying A may also modify B. What is
QUOTE good for, then? If you have eg. large constant lists that you
would like the compiler to coalesce, then putting them in as literal
constants gives the compiler licence to do so.

http://random-state.net/files/nikodemus-cl-faq.txt
====================================
Reply all
Reply to author
Forward
0 new messages