自 "quote就是构造一个list"似乎不对 quote会对多层生效吗 继续讨论:
C-h v 常常遇到 #1=some-value #1#
这样的值,如:
(let ((s "HELLO"))
(list s s))
;; => (#1="HELLO" #1#)
(let ((l (list 1)))
(list l l))
;; => (#1=(1) #1#)
使用同一个值两次时,Emacs 只保存第一次的值,第二次使用引用(Shared)。字符串、数组、列表是这样的,数字、符号则不会。
与此相关的一个常见问题:'(1 2 3)
跟 (list 1 2 3)
的区别:
(mapcar (lambda (x) (cons x (list 1 2 3)))
'(a b c))
;; => ((a 1 2 3) (b 1 2 3) (c 1 2 3))
如果要用 '(1 2 3)
得到和 (list 1 2 3)
一模一样的结果需要用:
(list (cons 'a '(1 2 3))
(cons 'b '(1 2 3))
(cons 'c '(1 2 3)))
;; => ((a 1 2 3) (b 1 2 3) (c 1 2 3))
下面这样是不行的:
(mapcar (lambda (x) (cons x '(1 2 3)))
'(a b c))
;; => ((a . #1=(1 2 3)) (b . #1#) (c . #1#))
用 M-x disassemble
很容易看出 '(1 2 3)
和 (list 1 2 3)
的区别:
(defun foo (x)
(cons x '(1 2 3)))
byte code for foo:
args: (x)
0 varref x
1 constant (1 2 3)
2 cons
3 return
(defun bar (x)
(cons x (list 1 2 3)))
byte code for bar:
args: (x)
0 varref x
1 constant 1
2 constant 2
3 constant 3
4 list3
5 cons
6 return
大致可以认为一个 Quoted Object 是一个「常量」,跟所在的执行环境绑定在了一起。但问题在于这个「常量」没有强制性,Emacs 不会阻止用户修改常量,比如 foo
的定义会被这样一种方式修改:
(defun foo (x)
(cons x '(1 2 3)))
(setf (nth 1 (foo 100)) 1111)
byte code for foo:
args: (x)
0 varref x
1 constant (1111 2 3)
2 cons
3 return
所以如果你的代码中有 '(1 2 3)
,第一次执行它是 (1 2 3)
,第二次就不能确定了,不像 (list 1 2 3)
每次执行都是 (1 2 3)
。
而如果只可能执行一遍,比如给变量设置初值,'(1 2 3)
和 (list 1 2 3)
没有区别:
(defvar foo '(1 2 3))
(defvar bar (list 1 2 3))