Что делает `symbol-value`?


13

Документы сделали меня не мудрее

Эта функция возвращает значение, хранящееся в ячейке значения символа. Здесь хранится текущее (динамическое) значение переменной. Если переменная не имеет локальной привязки, это просто ее глобальное значение. Если переменная void, сообщается об ошибке void-variable.

Какой смысл в значении символа? Где и когда мне нужно это использовать?


3
Спасибо за попытку найти ответ, спросив Emacs. Это правильный подход: сначала спросите Emacs, а затем спросите здесь о том, что еще не ясно, дайте нам знать в вашем вопросе, что вы уже пробовали. Престижность!
Дрю

Ответы:


13

Это необходимо, когда в коде Elisp вы хотите получить значение символа, то есть его значение, если рассматривать его как переменную.

Имейте в виду, что символ Elisp имеет несколько характеристик / особенностей:

  • У него есть имя (которое symbol-nameдает функция )
  • Может иметь значение, когда рассматривается как переменная (которая symbol-valueдает)
  • Он может называть функцию, когда рассматривается как функция (которая symbol-functionдает)
  • У него есть список свойств (который symbol-plistдает)

Думайте о символе как об объекте с различными атрибутами.


1
Также обратите внимание, что (как указано в документации) symbol-valueвсегда возвращает динамическое связывание для символа. Вы не можете получить лексические значения таким способом.
phils

2
Также см. C-h i g (elisp) Symbol Components RETДокументацию по этим различным символьным ячейкам / компонентам.
Филс

@phils: Хм, интересно (setq lexical-binding t) (let ((v 42)) (message "lex: %S, val: %S" lexical-binding (symbol-value 'v))). Но да, это то, что он говорит в (elisp) Lexical Binding: « функционирует как symbol-value, boundp'и set'только извлекает или изменяет динамическое связывание переменной (т. Е. Содержимое ячейки значения ее символа) ». Однако об этом ничего не сказано Symbol Components.
Дрю

10

(Doh, @Drew уже выдвинул некоторые из следующих. Во всяком случае, вот некоторые дополнительные детали.)

Как объясняется на странице руководства по компонентам символов , для каждого символа есть четыре компонента (ячейки): ячейка с именем печати, ячейка значения, определение функции и список свойств. Ячейка значения или ячейка функции может быть недействительной, а список свойств может быть нулевым.

В руководстве также указано:

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

Вот почему вы можете иметь, например:

(setq test "kittens")
(defun test ()
  (message "puppies"))
(symbol-value 'test)    ; => "kittens"
(symbol-function 'test) ; => (lambda nil (message "puppies"))

1
Ах, то, что это ценность, а не функция, сделало ее намного проще для понимания. Благодарю.
Несчастный Кот

8

Вот небольшая историческая справка (я еще не родился, когда произошли описанные события, поэтому, возможно, кто-то более знающий исправит меня. Все это от чтения старых статей и некоторых книг).

Не обращая внимания на отказ от ответственности, кажется, что во времена Фортрана против Лиспа «символическое» было своего рода модным словом, как сегодня «объектно-ориентированное». Т.е. программы обычно рассматривались как просто огромные математические формулы, в которых числа в конечном итоге будут вставлены, а заполнители для чисел были несущественными. Вся символическая информация, содержащаяся в программе, исчезнет, ​​как только эта программа будет запущена, скомпилирована или интерпретирована. Новинка Lisp заключалась в том, что он позволял символам сохраняться в программе даже после ее запуска, компиляции или интерпретации. Это вдохновило такую ​​терминологию, как «символическая алгебра» (как при манипулировании алгебраическими формулами, как это делается на бумаге / доске, а не путем прямого вычисления). Чтобы поддержать это (и другие символические вещи), символы должны были быть снабжены именем и некоторыми свойствами. С несимволической точки зрения можно сказать, что «символы просто называются указателями», и хотя это не так, если они являются чем-то большим, чем указатели на структуры, но для практических целей символы обозначают левые сторона стороны пары переменная-значение. Это также позволяет увидетьsymbol-value функция разыменования указателя в несимвольных языках.

Современные Лиспы отличаются тем, что значения могут быть связаны с одним символом (предположим, у вас был не символический язык с несколькими стеками / кучами памяти, вы можете представить себе ситуацию, когда один и тот же указатель имеет значение при интерпретации в контексте разных стеков / отвалы). Таким образом, языки Lisp2 (Emacs Lisp является одним из таких языков) имеют отдельное хранилище для функций и переменных, поэтому существует также метод symbol-function, который «разыменовывает указатель, указывающий на хранилище функций». Схема не имеет этого специального хранилища, а Clojure AFAIK не имеет ни того, ни другого symbol-plist.


7

Небольшая демонстрация:

(setq v1 10)
;;10
v1
;;10
(setq v2 'v1)
;;v1
v2
;;v1
(symbol-value v2)
;;10 
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.