Подтвердить что ты не робот

Какая разница между defvar, defparameter, setf и setq

Я нашел Похожие вопросы.

Но я не совсем понимаю это объяснение.

Итак, я пытаюсь запустить clisp со следующим примером:

  [1]> (defvar a 5)
  A
  [2]> (+ a 1)
  6
  [3]> (defparameter b 5)
  B
  [4]> (+ b 1)
  6
  [5]> (setf c 5)
  5
  [6]> (+ c 1)
  6
  [7]> (setq d 5)
  5
  [8]> (+ d 1)
  6
  [9]> (let ((a 500)) (+ a 1))
  501
  [10]> (let ((b 500)) (+ b 1))
  501
  [11]> (let ((c 500)) (+ c 1))
  501
  [12]> (let ((d 500)) (+ d 1))
  501
  [13]> 

То, что я нашел, абсолютно то же самое.

Я не могу понять, что с ними другое?

4b9b3361

Ответ 1

DEFPARAMETER всегда присваивает значение. Итак:

[1]> (defparameter a 1)
A
[2]> (defparameter a 2)
A
[3]> a
2

в то время как DEFVAR делает это только один раз, поэтому:

[4]> (defvar b 1)
B
[5]> (defvar b 2)
B
[6]> b
1

SETF - это макрос, который использует SETQ внутри, но имеет больше возможностей. В некотором смысле это более общий оператор присваивания. Например. с помощью SETF вы можете:

[19]> (defparameter c (list 1 2 3))
[21]> (setf (car c) 42)                                              
42
[22]> c
(42 2 3)

но вы не можете сделать это с помощью SETQ:

[23]> (setq (car c) 42)                                              
*** - SETQ: (CAR C) is not a symbol
The following restarts are available:
USE-VALUE      :R1      Input a value to be used instead.
ABORT          :R2      Abort main loop
Break 1 [24]> abort

Ответ 2

Оба defvar и defparameter объявят переменную как "динамически измененную переменную". Кроме того, defparameter всегда будет устанавливать значение переменной в значение, которое вы передаете в качестве второго аргумента. Это отличается от defvar, оно установит только значение переменной, если оно ранее не было установлено.

Определение переменной с setf или setq в глобальной лексической области undefined. Некоторые реализации создадут для вас динамически скопированную переменную, некоторые - нет. Вы можете видеть диагностические сообщения, когда вы делаете это в первый раз.

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

* (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) не будет делать то же самое).