我不理解以下代码:
(defun my-test ()
(let ((temp '(())))
(format t "temp: ~a~%" temp)
((lambda ()
(push 5 (first temp))))))
;; Execute this call twice in a row.
(my-test)
输出:
temp: (NIL)
temp: ((5))
temp
如何保存值?我知道有以下警告,但我不了解此行为背后的逻辑。
; in: DEFUN MY-TEST
; (PUSH 5 (FIRST TEMP))
; --> LET*
; ==>
; (SB-KERNEL:%RPLACA #:TEMP0 (CONS 5 (FIRST #:TEMP0)))
;
; caught WARNING:
; Destructive function SB-KERNEL:%RPLACA called on constant data: (NIL)
; See also:
; The ANSI Standard, Special Operator QUOTE
; The ANSI Standard, Section 3.2.2.3
;
; compilation unit finished
; caught 1 WARNING condition
以下代码输出的结果相同:
(flet ((my-fct ()
(let ((temp '(())))
(format t "temp: ~a~%" temp)
((lambda ()
(push 5 (first temp)))))))
(my-fct)
(my-fct))
(let ((fct (lambda ()
(let ((temp '(())))
(format t "temp: ~a~%" temp)
((lambda ()
(push 5 (first temp))))))))
(funcall fct)
(funcall fct))
但是这个有效:
;; Execute this call twice in a row.
((lambda ()
(let ((temp '(())))
(format t "temp: ~a~%" temp)
((lambda ()
(push 5 (first temp)))))))
这也是可行的:
(defun my-test ()
(let ((temp (list ())))
(format t "temp: ~a~%" temp)
((lambda ()
(push 5 (first temp))))))
(my-test)
这也是:
(defun my-test ()
(let ((temp (list (list))))
(format t "temp: ~a~%" temp)
((lambda ()
(push 5 (first temp))))))
(my-test)
但不是这个:
(defun my-test ()
(let ((temp `(,(list))))
(format t "temp: ~a~%" temp)
((lambda ()
(push 5 (first temp))))))
(my-test)
答案 0 :(得分:5)
Common Lisp规范没有指定当您尝试变异常量数据时会发生什么。常量数据为:
quote
运算符产生的数据这样做的目的是允许实现使用只读存储器(无需gc对其进行扫描)来获取常量,并允许对相同的常量重新使用存储。
代码如下:
(defun foo ()
... '(()) ...)
可以转换为:
(defconstant +foo1+ '(()))
(defun foo ()
... +foo1+ ...)
不偏离标准的文字或精神。