Допустим, что некоторый код оценивается шаг за шагом в 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
верно ли для этого буфера?». Если да, Emacs оценивает my-abc
, используя лексическую область, в противном случае, используя динамическую область.
Некоторое обновление: также, когда код цитируется как данные и затем передается в функцию eval
, ответ на (A) не будет буфером. Тем не менее, eval
создает воображаемый буфер для размещения кода и устанавливает локальное значение буфера lexical-binding
для этого буфера во второй аргумент, переданный eval
. Ответом на (A) является , а не буфер, содержащий вызов eval. Это мнимый буфер.
Для макросов Lisp, когда выполняется какой-то макрорасширенный код, это выглядит так, как будто расширенный код записывается в буфер, содержащий код, который вызвал макрос. Поэтому ответом на (A) в этом случае является не буфер, который определил макрос, но буфер, в котором находится код, который вызвал макрос.