И defvar
, и defparameter
объявят переменную как "переменную с динамической областью действия".Кроме того, defparameter
всегда будет устанавливать значение переменной равным значению, которое вы передаете в качестве второго аргумента.Это отличается от defvar
, оно будет устанавливать значение переменной, только если оно ранее не было установлено.
Определение переменной с помощью setf
или setq
в глобальной лексической области не определено,Некоторые реализации создадут переменную с динамической областью действия для вас, некоторые - нет.Вы можете увидеть диагностические сообщения, когда вы делаете это в первый раз.
Чтобы понять разницу между переменными в лексической и динамической областях, попробуйте следующий фрагмент кода:
* (defvar *a* 1)
*A*
* (let ((*a* 5)) (defun demo-a () *a*))
DEMO-A
* (let ((b 5)) (defun demo-b () b))
DEMO-B
* (let ((*a* 100)) (demo-a))
100
* (let ((b 100)) (demo-b))
5
Здесьмы создаем переменную с динамической областью действия и функцию, которая возвращает значение (определенное внутри привязки, где оно имеет другое значение при создании функции, в этом нет необходимости, и это делается только для того, чтобы выглядеть похожим на лексическое замыкание над b).Затем мы определяем новую переменную и определяем функцию, возвращающую ее значение.
После этого мы вызываем обе функции внутри замыканий, привязывая значение к переменной с тем же именем.В случае динамического определения объема это та же самая переменная.В случае лексического замыкания (b) они просто имеют одно и то же имя, но не являются одной и той же переменной, поскольку они определены в двух разных лексических замыканиях.
Что касается разницы между setf
иsetq
, попробуйте всегда использовать setf
(я не могу вспомнить ни одного примера, где (setq blah blahblah)
работал бы, а (setf blah blahblah)
не делал бы то же самое).