这的确是你的意思是增加x
,或者至少有一种方式。然而,这不是你如何绑定x
。在CL中,您需要在使用它之前为名称建立一个绑定,而您不需要通过分配给它。所以,举例来说,这个代码(在一个新的CL图像)是不合法的CL:
(defun bad()
(setf y 2))
通常,这会导致编译时警告和运行时错误,虽然它可以做别的事情:其行为没有定义。
你做了什么,特别是,其实比这更糟糕的:你已经撞向一个值的x
的symbol-value
(与set
,它做到这一点),然后假定像(incf x)
会的工作,它是极不可能做到。例如考虑这样的事情:
(defun worse()
(let ((x 2))
(set 'x 4)
(incf x)
(values x (symbol-value 'x))))
这是(不像bad
)法人代码,但它可能是你想要它做的事情没有做。
许多CL实现做允许分配给先前未绑定的变量在顶层,因为在会话环境中它很方便。但这些作业的确切含义超出了语言标准。
CMUCL及其衍生产品(包括SBCL)在历史上对此比其他实施更为严肃。我认为原因是解释者比其他人更加严肃,并且/或者他们秘密地编译了所有的东西,编译器挑选了一些东西。
的另一个问题是,CL有顶层变量略显尴尬的语义:如果你去建立一个顶层以正常的方式结合的努力,与defvar
&朋友,那么你也引起变量是特殊的 - 动态范围 - 这是一个普遍的影响:它使所有该名称的绑定特殊。这往往是一个非常不受欢迎的后果。 CL作为一种语言,没有顶级词汇变量的概念。因此,有多少实现做了什么,因此,有什么样的顶级绑定的非形式化的概念并不意味着一个特殊的声明:如果你只是在最顶层说(setf x 3)
,那么这不会使整个环境。但后来出现了各种尴尬的问题:在这样做之后,例如(symbol-value 'x)
的结果是什么?
幸运的是CL是一种功能强大的语言,它很有可能在定义语言中的顶级词法变量。这是一个非常冒险的实现,名为deflexical
。请注意,有更好的实现(包括我至少有一个,我现在找不到):这并不意味着是一个防弹解决方案。
(defmacro deflexical (var &optional value)
;; Define a cheap-and-nasty global lexical variable. In this
;; implementation, global lexicals are not boundp and the global
;; lexical value is not stored in the symbol-value of the symbol.
;;
;; This implementation is *not* properly thought-through and is
;; without question problematic
`(progn
(define-symbol-macro ,var (get ',var 'lexical-value))
(let ((flag (cons nil nil)))
;; assign a value only if there is not one already, like DEFVAR
(when (eq (get ',var 'lexical-value flag) flag)
(setf (get ',var 'lexical-value) ,value))
;; Return the symbol
',var)))
来源
2016-10-18 10:56:50
tfb
看起来行我需要更多的阅读。你能建议一个好的来源吗? – Hydrocat
@Hydrocat:我不是一个真正合适的人:当我学习CL时,实际上只有CLtL(虽然是一本有趣的书)并不是真正的好的当前信息的来源。我喜欢保罗格雷厄姆的书籍,我认为这些书籍现在是免费的,而且这个规范不适合学习。也许别人有更好的和更近期的想法。 – tfb
哦,很好:)我其实有一本格雷厄姆的书。那么我应该在好手中! – Hydrocat