В Emacs 24 теперь есть лексически измененные переменные. Разумеется, он также имеет динамически измененные переменные. Теперь, когда у него есть оба, я довольно смущен, когда переменная будет иметь какой-то объем. Там переменная lexical-binding
, которая контролирует, когда включена лексическая привязка, и я думаю, что я что-то прочитал о defvar
, объявляющем переменную с динамической областью, но в целом я довольно потерян. Есть ли хорошее объяснение где-то в Emacs 24 новых правилах? Или по-другому, когда я смотрю на переменную в Emacs Lisp код, написанный для Emacs 24, как я могу определить, какую область действия использует эта переменная?
Каковы новые правила изменения переменных в Emacs 24?
Ответ 1
Руководство является окончательным источником. Начать здесь:
C-h i g (elisp) Variable Scoping
RET
Я изначально цитировал руководство в этом ответе, но эта информация (датированная Emacs 24.0.90.1) была немного устаревшей. Лучше прочитать руководство изнутри Emacs, чтобы информация была верна для используемой версии.
Если вам особенно хочется прочитать его на веб-странице, текущая версия:
http://www.gnu.org/software/emacs/manual/html_node/elisp/Variable-Scoping.html
Ответ 2
Скажем, что некоторый код оценивается пошагово в Emacs (либо потому, что вы только что делали C-x C-e
, либо из-за того, что загружается файл Emacs Lisp или из-за того, что выполняется функция с крючка и т.д.), и что Emacs собирается оценить my-abc
внутри этого кода. Может быть, my-abc
является локальной переменной в этом коде или, возможно, не объявляется или, возможно, имеет какое-то глобальное значение и т.д. В любом случае, текущий шаг - это оценка my-abc
. В этот момент Emacs проверяет только две вещи, чтобы решить, следует ли оценивать my-abc
с помощью лексической области или нет.
Первое, что проверяет Emacs: "есть my-abc
специальная переменная?". Ответ на этот вопрос - да, если (defvar my-abc ...)
или (defcustom my-abc ..)
или т.д. Был запущен в любой момент в прошлом. Возможно, (defcustom my-abc ..)
был запущен при загрузке некоторого другого файла Emacs Lisp, или, возможно, вы оценили код, содержащий (defvar my-abc ...)
в буфере нуля, или, возможно, нет. Если ответ по какой-либо причине да, Emacs в этой точке будет оценивать my-abc
с помощью динамической области.
Если ответ отрицательный, то Emacs проверяет вторую вещь, которая есть (A) "где этот код (содержащий использование my-abc
), который я (Emacs) am stepping?". Это не (B) "каков текущий буфер?". Если вы просто нажали Cx Ce в буфере, скажите foo.el
, и если выражение, нажатое Cx ce, содержит вызов функции с именем mah-hello
, которая определена в mah-stuff.el
, и если тело функции mah-hello
содержится вызов функции с именем my-hello
, которая определена в my-stuff.el
, и если в теле функции my-hello
содержится использование переменной с именем my-abc
, тогда, когда Emacs в конечном итоге получают выполнение my-hello
, а затем это для оценки my-abc
там, в тот момент, когда Emacs задает вопрос A, он отвечает my-stuff.el
себе. Не буфер foo.el
, содержащий исходное выражение.
Затем Emacs спрашивает: "my-stuff.el
лексически скопированный буфер, другими словами, lexical-binding
true в этом буфере?". Если да, Emacs оценивает my-abc
, используя лексическую область, в противном случае используя динамическую область.
Некоторое обновление. Также, когда код цитируется как данные, а затем передается функции eval
, ответ на (A) не будет буфером. Тем не менее, как будто eval
образует воображаемый буфер для размещения кода и устанавливает для этого буфера локальное значение lexical-binding
для второго аргумента, переданного в eval
. Ответ на (A) не является буфером, содержащим вызов eval. Это мнимый буфер.
Для макросов Lisp, когда выполняется некоторый макрорасширенный код, он как бы расширенный код записывается в буфер, содержащий код, вызывающий макрос. Поэтому ответ на (A) в этом случае не является буфером, который определил макрос, но буфер, в котором находится код, называемый макросом.