2013-06-26 2 views
2

Я использую динамические переменные, давайте назовем один из них *x* со значением 10.Как эффективно использовать setf для динамической переменной через вызов функции?

Я хочу, чтобы изменить его значение с помощью вызова функции, передавая имя переменной в качестве параметра:

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

затем вызывая (change-value *x*). Если я правильно понимаю, varname принимает локальный масштаб, и поэтому setf не имеет эффекта снаружи change-value. Итак, *x* остается 10 после этого.

Мой вопрос: есть ли способ сделать *x* равным 20 через вызов функции, аналогичный вышесказанному? Я попытался добавить (proclaim '(special varname)) и (declare (special varname)), и они, кажется, ничего не делают.

О, и определение макроса делает более или менее то, что я хочу, но я сомневаюсь, что это хорошая практика:

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

(change-value-macro *x*) 
+0

'(DEFUN переключающий стоимость из-х (значение) (SEtF * х * значение))'? Или просто '(setf * x * value)' непосредственно? –

ответ

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*).

+0

Спасибо за ответ. Теперь не было бы следствием перехода 10 в результате аргумента (setf 10 20)? Разве мы не должны получить ошибку? –

+1

@HeitorChang: вы получите ошибку, если вы передадите неуказанную '* x *' в мою версию. Обратите внимание, что 'setf' does * not * оценивает' varname' в вашей версии, поэтому вы не устанавливаете от 10 до 20, вы устанавливаете 'varname' на 20. – sds

+0

@sds OK, я ценю вашу помощь :) –

2

Это похоже на работу:

(defparameter *x* 'initial) 

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

(change-dyn '*x* 'final)