Йорг отвечает в правильном направлении.Позвольте мне добавить к этому немного.
Я расскажу о Лиспах, похожих на Common Lisp.
Символы в виде структуры данных
Символ - это реальная структура данных в Лиспе.Вы можете создавать символы, вы можете использовать символы, вы можете хранить символы, вы можете передавать символы и символы могут быть частью больших структур данных, например списков символов.Символ имеет имя, может иметь значение и может иметь значение функции.
Таким образом, вы можете взять символ и установить его значение.
(setf (symbol-value 'foo) 42)
Обычно можно написать (setq foo 42)
или (set 'foo 42)
или (setf foo 42)
.
Символы в коде, обозначающие переменные
Но!
(defun foo (a)
(setq a 42))
или
(let ((a 10))
(setq a 42))
В обеих вышеприведенных формах в исходном коде есть символы, и a
записывается как символ, и использование функции READ
для чтения этого источника возвращает символ a
в некотором списке.Но операция setq
НЕ устанавливает значение символа a
в 42
.Здесь LET
и DEFUN
представляют VARIABLE a
, который мы пишем с символом.Таким образом, операция SETQ
устанавливает значение переменной на 42
.
Лексическое связывание
Итак, если мы посмотрим:
(defvar foo nil)
(defun bar (baz)
(setq foo 3)
(setq baz 3))
Введем глобальную переменную FOO
.
В столбце первая SETQ
задает значение символа глобальной переменной FOO
.Второй SETQ
устанавливает локальную переменную BAZ
в 3
.В обоих случаях мы используем один и тот же SETQ
и записываем переменную как символ, но в первом случае FOO
передает глобальную переменную, и эти значения хранятся в значении символа.Во втором случае BAZ
обозначает локальную переменную и то, как значение сохраняется, мы не знаем.Все, что мы можем сделать, это получить доступ к переменной, чтобы получить ее значение.В Common Lisp нет способа взять символ BAZ
и получить значение локальной переменной.У нас нет доступа к привязкам локальной переменной и их значениям с помощью символов.Это часть того, как лексическое связывание локальных переменных работает в Common Lisp.
Это приводит, например, к наблюдению, что в скомпилированном коде без записанной отладочной информации символ BAZ
пропал.Это может быть регистр в вашем процессоре или реализованный другим способом.Символ FOO
все еще там, потому что мы используем его как глобальную переменную.
Различное использование символов
Символ - это тип данных, структура данныхв Лисп.
Переменная - это концептуальная вещь.Глобальные переменные основаны на символах.Локальных лексических переменных нет.
В исходном коде мы пишем все виды имен для функций, классов и переменных с использованием символов.
Существует некоторое концептуальное перекрытие:
(defun foo (bar) (setq bar 'baz))
В приведенном выше коде SOURCE defun
, foo
, bar
, setq
и baz
являются символами.
DEFUN
является символом, обеспечивающим макрос.FOO
- это символ, обеспечивающий функцию.SETQ
является символом, предоставляющим специального оператора.BAZ
- символ, используемый в качестве данных.Таким образом, цитата до BAZ
.BAR
является переменной.В скомпилированном коде его символ больше не нужен.