在 SBCL 中,为什么在 Common Lisp 中的 LET 中将 *print-circle* 设置为 T 不起作用,但 SETF 可以正常打印循环列表?

问题描述 投票:0回答:1

我注意到,如果我将 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就可以临时绑定它?

common-lisp sbcl dynamic-scope
1个回答
0
投票

这是因为打印仅由 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)
的值,从而再次卡住

© www.soinside.com 2019 - 2024. All rights reserved.