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

В чем разница между переменной и символом в LISP?

С точки зрения объема? Фактическая реализация в памяти? Синтаксис? Например, если (пусть a 1) является "a" переменной или символом?

4b9b3361

Ответ 1

Jörg отвечает в правильном направлении. Позвольте мне добавить немного.

Я расскажу о Lisps, которые похожи на Common Lisp.

Символы как структура данных

Символ представляет собой реальную структуру данных в 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 все еще существует, потому что мы используем его как глобальную переменную.

Различные применения символов

Символ - это тип данных, структура данных в Lisp.

Переменная - это концептуальная вещь. Глобальные переменные основаны на символах. Локальные лексические переменные не являются.

В исходном коде мы пишем все виды имен для функций, классов и переменных с помощью символов.

Существует некоторое концептуальное перекрытие:

(defun foo (bar) (setq bar 'baz))

В приведенном выше коде SOURCE DEFUN, FOO, bar, setq и BAZ - все символы.

DEFUN - символ, обеспечивающий макрос. FOO - символ, предоставляющий функцию. setq - символ, предоставляющий специальный оператор. BAZ - символ, используемый в качестве данных. Таким образом, цитата перед BAZ. bar - переменная. В скомпилированном коде его символ больше не нужен.

Ответ 2

Цитата из Общий Lisp HyperSpec:

символ n. object type symbol.

переменная n. a binding в "переменной" namespace.

привязка n. связь между name и тем, что обозначено этим именем. (...)

Время пояснения.

Что Lisp вызывает символы довольно близко к тому, что многие языки называют переменными. В первом приближении символы имеют значения; когда вы оцениваете выражение x, значение выражения представляет собой значение символа x; когда вы пишете (setq x 3), вы присваиваете новое значение x. В терминологии Lisp (setq x 3) связывает значение 3 с символом x.

Функция Lisp, которую не имеет большинство языков, состоит в том, что символы являются обычными объектами (символы являются первоклассными объектами в терминологии языка программирования). Когда вы пишете (setq x y), значение x становится любым значением y во время назначения. Но вы можете написать (setq x 'y), и в этом случае значение x является символом y.

Концептуально говоря, существует environment, который представляет собой таблицу ассоциаций от символов до значений. Оценка символа означает поиск его в текущей среде. (Среды тоже являются объектами первого класса, но это выходит за рамки этого ответа.) привязка относится к определенной записи в среде. Однако есть дополнительное осложнение.

Большинство диалектов Lisp имеют несколько пространств имен, по крайней мере пространство имен переменных и пространство имен функций. На самом деле среда может содержать несколько записей для одного символа, одну запись для каждого пространства имен. Переменная, строго говоря, является записью в среде в пространстве имен переменных. В повседневной терминологии Lisp символ часто упоминается как переменная, когда его привязка как переменная является тем, что вас интересует.

Например, в (setq a 1) или (let ((a 1)) ...) символ a является символом. Но так как конструкции действуют на привязку переменных для символа a, он обычно ссылается на a как переменную в этом контексте.

С другой стороны, в (defun a (...) ...) или (flet ((a (x) ...)) ...) символ a также является символом, но эти конструкции действуют на его привязку к функции, поэтому a не будет считаться переменной.

В большинстве случаев, когда символ отображается без кавычек в выражении, он оценивается путем поиска привязки переменной. Основное исключение состоит в том, что в вызове функции (foo arg1 arg2 ...) используется привязка функции для foo. Значение цитируемого символа 'x или (quote x) само, как и при любом цитируемом выражении. Конечно, существует множество специальных форм, в которых вам не нужно указывать символ, включая setq, let, flet, defun и т.д.

Ответ 3

Символ - это имя для вещи. Переменная является изменяемым указателем на изменяемое место хранения.

В приведенном фрагменте кода символы let и a являются символами. В рамках блока let символ a обозначает переменную, которая в настоящее время привязана к значению 1.

Но имя вещи - это не сама вещь. Символ a не является переменной. Это имя переменной. Но только в этом конкретном контексте. В другом контексте имя a может относиться к совершенно другой вещи.

Пример: символ jaguar может, в зависимости от контекста, обозначать

Ответ 4

Lisp использует среды, похожие на карты (ключ → значение), но с дополнительными встроенными механизмами для объединения сетей и контроля привязок.

Теперь символы довольно много, ключи (кроме символов специальной формы) и указывают на значение,
т.е. функция, целое число, список и т.д.
Поскольку Common Lisp дает вам способ изменить значения, т.е. С setq, символы в некоторых контекстах

(ваш пример) также являются переменными.

Ответ 5

Символ - это объект данных Lisp. A Lisp "form" означает объект Lisp, который предназначен для оценки. Когда сам символ используется как форма Lisp, т.е. Когда вы оцениваете символ, результатом является значение, связанное с этим символом. Значения способа, связанные с символами, являются глубокой частью langauge Lisp. Является ли символ объявленным как "особенным" или не сильно изменяет способ оценки.

Лексические значения обозначаются символами, но вы не можете манипулировать этими символами как объекты самостоятельно. По-моему, объяснение чего-либо в Lisp с точки зрения "указателей" или "местоположений" не является лучшим способом.

Ответ 6

Символ и переменная - это две разные вещи. Как и в математическом символе, это значение. И переменная имеет то же значение, что и в математике.

Но ваша путаница возникла из-за того, что символ является мета-представлением переменной.

То есть, если вы делаете

(setq a 42)

Вы просто определяете переменную a. Кстати, обычным хранилищем lisp является бросок структуры символа.

В общих символах губ есть структура с другим свойством. Каждый из них может иметь доступ к функции типа symbol-name, symbol-function...

В случае переменной вы можете получить доступ к его значению через s symbol-value

? (symbol-value 'a)
42

Это не обычный случай получения значения a.

? a
42

Обратите внимание, что символы самооценки означают, что если вы спросите символ, вы получите символ не symbol-value

? 'a
A

Ответ 7

Добавление примечания к приведенным выше ответам:

Новички в Lisp часто не уверены, для каких символов, помимо имен переменных. Я думаю, лучший ответ в том, что они похожи на константы перечисления, за исключением того, что вам не нужно объявлять их перед их использованием. Конечно, как объяснили другие, они также являются объектами. (Это не должно показаться странным для пользователей Java, в которых константы перечисления тоже являются объектами.)