如何通过函数调用有效地在动态变量上使用setf?

时间:2013-06-26 18:57:53

标签: scope lisp common-lisp

我正在使用动态变量,让我们调用其中一个*x*,其值为10.

我希望通过将变量的名称作为参数传递来通过函数调用来更改其值:

(defun change-value (varname)
  (setf varname 20))

然后调用(change-value *x*)。如果我理解正确,varname会占用本地范围,因此setfchange-value之外无效。因此,*x*之后仍为10。

我的问题是,有没有办法通过类似上面的函数调用使*x*等于20?我尝试添加(proclaim '(special varname))(declare (special varname)),但他们似乎没有做任何事情。

哦,定义一个宏会或多或少地做我想要的,但我怀疑这是好的做法:

(defmacro change-value-macro (varname)
  `(setf ,varname 20))

(change-value-macro *x*)

2 个答案:

答案 0 :(得分:6)

定义

(defparameter *x* 10)
(defun change-value (varname) ; the argument name is misleading!
  (setf varname 20))

并且调用(change-value *x*)不会给你带来任何东西,因为change-value是一个函数而你只是将10作为参数传递给它;它不知道涉及*x*。因此,该函数所做的是修改变量varname的局部绑定,将其从10更改为20并返回后者。

您需要传递symbol(变量名称)本身:

(defun change-value (varname)
  (setf (symbol-value varname) 20))

并将其称为(change-value '*x*)(请注意'之前的引号*x*

答案 1 :(得分:2)

这似乎有效:

(defparameter *x* 'initial)

(defun change-dyn (variable value)
  (setf (symbol-value variable) value))

(change-dyn '*x* 'final)