我注意到,如果我将 print-circle 设置为 T,那么它会打印循环列表:
CL-USER> (setf *print-circle* t)
T
CL-USER> (let ((x (list 1)))
(setf (cdr x) x)
x)
#1=(1 . #1#)
但是如果我尝试使用 let 来设置 print-circle,它会无限期地挂起。
CL-USER> (setf *print-circle* nil)
NIL
CL-USER> (let ((*print-circle* t)
(x (list 1)))
(setf (cdr x) x)
x)
;; hangs indefinitely
什么给予?我以为print-circle是一个特殊的“动态绑定”变量,因此使用let就可以临时绑定它?
这是因为打印仅由 REPL after 评估 let 完成,在这种情况下 print-circle 的临时设置已经消失了。
为了获得我想要的效果,我需要确保打印是在let内完成的:
CL-USER> (setf *print-circle* nil)
NIL
CL-USER> (let ((*print-circle* t)
(x (list 1)))
(setf (cdr x) x)
(prin1 x)
nil)
#1=(1 . #1#)
NIL
CL-USER>
请注意,
nil
之后的最后一个(prin1 x)
很重要,因为没有它,repl仍将尝试评估然后在LET之外打印(prin1 x)
的值,从而再次卡住