#emacs #elisp #lexical-scope #dynamic-scope #emacs24
#emacs #elisp #лексический охват #динамическая область действия #emacs24 #лексическая область #динамическая область
Вопрос:
В Emacs 24 теперь есть переменные с лексической областью видимости. Конечно, он также по-прежнему имеет переменные с динамической областью действия. Теперь, когда у него есть и то, и другое, я совершенно не понимаю, когда переменная будет иметь какую область видимости. Есть lexical-binding
переменная, которая контролирует, когда включена лексическая привязка, и я думаю, что я что-то читал о том defvar
, что теперь объявляется переменная с динамической областью видимости, но в целом я довольно потерян. Есть ли где-нибудь хорошее объяснение новых правил определения области действия Emacs 24? Или, другими словами, когда я смотрю на переменную в коде Emacs Lisp, написанном для Emacs 24, как мне определить, какую область видимости использует эта переменная?
Комментарии:
1. Если вы установили Emacs 24, эта информация доступна в информации. Откройте узел «Emacs Lisp» и нажмите
i
для поиска по индексу.2. У меня установлены как 23, так и 24, так что это немного сбивало с толку. Были записи «Elisp» и «Elisp (emacs-snapshot)». Теперь я это вижу. Кроме того, я иногда забываю, что Emacs — один из проектов с хорошей документацией и, вероятно, не тот тип, который объединяет основные новые функции без соответствующей документации.
Ответ №1:
Руководство является окончательным источником. Начните здесь:
C-hig (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 ...)
or (defcustom my-abc ..)
или etc выполнялись в любой момент в прошлом. Возможно (defcustom my-abc ..)
, был запущен при загрузке какого-либо другого файла Emacs Lisp, или, может быть, вы оценили какой-то код, содержащийся (defvar my-abc ...)
в буфере scratch, или, может быть, нет. Если по какой-либо причине ответ положительный, Emacs на этом этапе выполнит оценку my-abc
с использованием динамической области видимости.
Если ответ отрицательный, то Emacs проверяет второе, а именно (А) «где находится этот код (содержащий использование my-abc
), который я (Emacs) просматриваю?». Это не (B) «каков текущий буфер сейчас?». Если вы только что нажали C-x C-e, скажем foo.el
, в буфере, и если выражение, в котором вы нажали C-x c-e, содержало вызов функции с именем 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) в этом случае является не буфер, который определил макрос, а буфер, в котором находится код, вызвавший макрос.
Комментарии:
1. Отличное объяснение. Спасибо!