我正在尝试使用substitute-if
。在这里,我尝试用'((1) (2) (3) (4))
'(0)
中的值
[9]> (substitute-if '(0) #'evenp '((1) (2) (3) (4)) :start 1 :key #'car)
((1) #1=(0) (3) #1#)
我对列表中的#1=(0)
和#1
感到困惑。我希望它返回'((1) (0) (3) (0))
。
我是误解了substitute-if
的工作原理还是误解了列表的表示形式?
答案 0 :(得分:6)
我是误解了
substitute-if
的工作原理还是误解了列表的表示形式?
可能是后者。
#1=...
标记了数据结构中的一个点,而#1#
又指向了该结构。这样做的目的是表明两个元素都引用相同的列表。 (另请参见http://www.lispworks.com/documentation/HyperSpec/Body/02_dhp.htm。)
就像:
(let ((x '(0)))
(list '(1) x '(3) x))
由于它们引用同一个对象,因此,如果您要修改第二个列表,那么修改也会显示在第四个列表中。
答案 1 :(得分:3)
似乎您已将动态全局变量*print-circle*
设置为正确的值。如果您评估*print-circle*
,就会看到它。
; make a list (1 1 1 1 1 ...)
(defparameter *test* (list 1))
(setf (cdr *test*) *test*)
(setf *print-circle* t)
(substitute-if '(0) #'evenp '((1) (2) (3) (4)) :start 1 :key #'car)
; ==> ((1) #1=(0) (3) #1#)
*test*
; ==> #1=(1 . #1#)
(setf *print-circle* nil)
(substitute-if '(0) #'evenp '((1) (2) (3) (4)) :start 1 :key #'car)
; ==> ((1) (0) (3) (0))
*test* ; never finishes
最后一个将挂起,直到用完内存。急于取消它,否则一旦系统使用了所有可用的内存和缓冲区并开始让系统交换其他东西,您的系统肯定会呆滞。
这就是为什么我们有*print-circle*
的原因。查看圆形列表的能力。打印的数据结构始终相同,因此仅显示方式不同。
当您使用substitute-if
并替换为'(0)
时,该地址在内存中有一个地址,因此,当*print-circle*
为真时,它将只打印一次,而其他参考将显示为参考因为系统会寻找相同的对象,而不是真正的圆形对象。