Как Лисп динамически назначает символы?Базовая структура данных / механизм символа Lisp? - PullRequest
2 голосов
/ 30 марта 2012

Lisp позволяет вам определять символы, такие как A и B, в списке, например,

(setf mylist '(+ 1 2 A))

. Затем вы можете вернуться в любое время и установить для A значение, например,.(set 'A 100).В этот момент вы можете сделать (eval mylist) и вернуться обратно 103. Затем вы можете повторно присвоить A любому новому значению.

Похоже, что Лисп сохраняет как литерал "A" (имя символа), так и присвоенное ему значение.Это позволяет динамическое назначение / переназначение переменных.Это вроде как список поиска.Какова основная структура данных или механизм, который позволяет это?

РЕДАКТИРОВАТЬ: В частности, как это делается внутренне (или внешне, так как пакеты, кажется, непосредственно вовлечены)?Ищете подробный технический ответ, который фокусируется на том, как это реализовано в Lisp-2 .

Ответы [ 2 ]

5 голосов
/ 31 марта 2012

Обратите внимание, что '(+ 1 2 A) - это не переменная, а форма (кавычка (+ 1 2 A)), которая оценивает объект.A внутри списка - это символ, но это не переменная.

Переменная - это место хранения, обозначаемое символом.

Re: Как работает такой язык, как Лиспделать этот вид оценки во время выполнения?

(Common) Lisp имеет два вида переменных: динамические и лексические.Динамические переменные можно оценивать во время выполнения в том смысле, что вы можете взять символ и определить, имеет ли он привязку динамической переменной, и получить или назначить эту привязку.

Лексические переменные - это те, которые "запекаются""во время компиляции: не существует переносимого способа отразить их по имени.

Оба типа переменных полезны для разных целей.

Динамическая переменная может храниться в месте, котороесвязанный с символом, называется его значение ячейки .(Этот термин фактически появляется в ANSI Common Lisp).Символ используется как своего рода ключ для извлечения ячейки (если она есть).Например, ячейка значения может быть полем cdr некоторой cons-ячейки, которая хранится в хэш-таблице, где ключи являются символами.Возможны различные реализации.

Существует сложность в том, что Lisp поддерживает локальную привязку динамических переменных: то есть вы можете использовать let или другие конструкции привязки для создания локальных привязок для динамических переменных, которые скрывают любую существующую привязку.Когда конструкция выходит (любым способом: включая нелокальный выход через throw и т. Д.), Скрытая привязка восстанавливается.Эта динамическая область видимости должна быть каким-то образом реализована, и это означает, что поиск динамической переменной не обязательно просто преследует указатель от символа на ячейку значения.

Еще одним осложнением является то, что пользователиМногопоточные Lisps хотят иметь привязку динамических переменных к каждому потоку.

Здесь может быть больше информации: http://en.wikipedia.org/wiki/Scope_%28computer_science%29#Dynamic_scoping

2 голосов
/ 31 марта 2012

В Common Lisp символы являются объектами сами по себе и могут иметь именованные свойства со значениями, связанными с ними. Символы создаются ( interned в текущей упаковке) при чтении, например:

> 'a
A

Вы можете проверить их с помощью (describe 'a) или (inspect 'a) (используя CLISP здесь). Вы можете установить этот символ с помощью (set 'a 1). Но вы также можете позвонить (defun a (x) (+ 1 x)) после этого. Проверка символа 'a теперь показывает, что он содержит одновременно и значение, и определение функции. Это отражает Common Lisp, имеющий отдельные пространства имен для значений переменных и функций. Символы хранят эту дополнительную информацию в своих списках свойств:

[19]> (symbol-value 'a)
1
[20]> (symbol-function 'a)
#<FUNCTION A (X) (DECLARE (SYSTEM::IN-DEFUN A)) (BLOCK A (+ X 1))>
[21]> (symbol-plist 'a)
(SYSTEM::DEFINITION
 ((DEFUN A (X) (+ X 1)) .
  #(NIL NIL NIL NIL ((DECLARATION OPTIMIZE DECLARATION)))))

[44]> (setf (get 'a 'prop1) 12)
12
[45]> (symbol-plist 'a)
(PROP1 12 SYSTEM::DEFINITION
 ((DEFUN A (X) (+ X 1)) .
  #(NIL NIL NIL NIL ((DECLARATION OPTIMIZE DECLARATION)))))

Смотри также

http://www.lispworks.com/documentation/HyperSpec/Body/f_get.htm#get http://www.lispworks.com/documentation/HyperSpec/Body/f_intern.htm#intern

...