Common lisp ";“设置”;作用

Common lisp ";“设置”;作用,common-lisp,dynamic-binding,lexical-scope,Common Lisp,Dynamic Binding,Lexical Scope,我很难理解一些有经验的人可能理解的代码的工作原理: (let ((x 0)) (loop for var in '(x) do (set var 3)) x) 我的期望是表达式应该返回3,即x的新值,但它实际上返回0。为什么x不能复位?是否有其他方法可以迭代变量列表并为其赋值?不支持使用符号访问词汇变量。 Common Lisp不允许您通过符号访问词汇变量。默认情况下,变量按词汇绑定 特殊变量使用动态绑定。 它与使用动态绑定的特殊变量一起工作: CL-USER 14 >

我很难理解一些有经验的人可能理解的代码的工作原理:

(let ((x 0))
  (loop for var in '(x)
    do (set var 3))
  x)

我的期望是表达式应该返回3,即x的新值,但它实际上返回0。为什么x不能复位?是否有其他方法可以迭代变量列表并为其赋值?

不支持使用符号访问词汇变量。

Common Lisp不允许您通过符号访问词汇变量。默认情况下,变量按词汇绑定

特殊变量使用动态绑定。

它与使用动态绑定的特殊变量一起工作:

CL-USER 14 > (let ((x 0))
                (declare (special x))
                (loop for var in '(x) do (set var 3))
                x)
3
或者,您可以声明一个全局特殊变量,该特殊声明扩展到
let
绑定。这也是为什么人们会用命名约定在视觉上标记它们。我们写
*foo*
,而不是
foo

CL-USER 15 > (defvar *x123* 0)
*X123*

CL-USER 16 > (let ((*x123* 1))
               (loop for var in '(*x123*) do (set var 3))
               *x123*)
3

X
是一个词汇变量
SET
仅设置符号的值槽(换句话说,它设置全局变量的值)。@jkiiski:这是答案,不是注释。已弃用,因此不应使用它。使用
setf
special form来改变绑定的特殊全局或词法。基于看起来相同的符号更新绑定可能需要使用其他数据结构(如哈希表)来解决。您可以稍微扩展一下通过符号不访问词法变量的含义吗?例如,词法变量是否具有常用的符号槽,如打印名称、符号值、符号函数、道具列表等?或者lex-var从来没有符号作为其符号值?谢谢你的澄清,如果这是基本的,我很抱歉。第二,我希望避免使用全局变量。用户将提供变量名称(由宏获取)。目前,我正在用这些变量名构造一个let子句(在加载时)(请参见上面的示例,其中有一个变量名为x),然后在主体中适当地设置它们的值。如果lex vars不能使用“set”,那么“setq”(或“setf”)是唯一的出路吗?但看起来我无法将所有这些变量名分组到一个列表中,并使用循环变量处理每个变量。是否有其他方法来设置let中的值(所有数字)?(续下)我唯一的另一个想法可能是创建一个单独的用户包(或者使用:关键字包),并在那里实习这些名称。但这可能需要一些重要的代码重写/重新思考。寻找任何有经验的见解。谢谢,好的,谢谢雷纳。通过进一步阅读,我已经能够纠正一些关于词汇和特殊变量的错误想法。忽略我之前的评论。我可以使用你提到的(声明(特殊…)解决方案。