2011-10-04 17 views
18

В Emacs 24 теперь есть лексически измененные переменные. Разумеется, он также имеет динамически измененные переменные. Теперь, когда у него есть оба варианта, я довольно смущен, когда переменная будет иметь какой-то объем. Есть переменная lexical-binding, которая контролирует, когда включена лексическая привязка, и я думаю, что я что-то прочитал о defvar, объявляя переменную с динамической областью, но в целом я довольно потерян. Есть ли хорошее объяснение где-то в новых правилах Emacs 24? Или по-другому, когда я смотрю на переменную в коде Emacs Lisp, написанную для Emacs 24, как я могу определить, какую область использует эта переменная?Каковы новые правила изменения переменных в Emacs 24?

+2

Если вы установили Emacs 24, эта информация доступна в информации. Откройте узел «Emacs Lisp» и нажмите «i», чтобы найти индекс. –

+0

У меня установлены 23 и 24, поэтому это было немного запутанно. Были записи «Elisp» и «Elisp (emacs-snapshot)». Я вижу это сейчас. Кроме того, я иногда забываю, что Emacs является одним из проектов с хорошей документацией и, вероятно, не для того, чтобы объединить основные новые функции без соответствующей документации. –

ответ

21

Руководство является окончательным источником. Начало здесь:

Chяг(elisp) Variable ScopingRET

я первоначально процитировал руководство в этом ответе, но эта информация (уходящую в Emacs 24.0.90.1) был немного из Дата. Лучше прочитать руководство изнутри Emacs, чтобы информация была верна для используемой вами версии.

Если вы особенно хотите, чтобы прочитать его на веб-странице, текущая версия:
http://www.gnu.org/software/emacs/manual/html_node/elisp/Variable-Scoping.html

3

Допустим, что некоторые код оцениваемого шаг за шагом в 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) перешагивает?». Это не (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) в этом случае равен , а не буфер, определяющий макрос, но буфер, в котором находится код, называемый макросом.

+0

Отличное объяснение. Благодаря! – killdash9