¿Cuáles son las nuevas reglas para el alcance de variables en Emacs 24?
elisp lexical-scope (2)
Emacs 24 ahora tiene variables de ámbito léxico. Por supuesto, también tiene variables de alcance dinámico. Ahora que tiene ambos, estoy bastante confundido acerca de cuándo una variable tendrá qué tipo de alcance. Hay una variable de lexical-binding
que controla cuando el enlace léxico está habilitado, y creo que leí algo acerca de que la defvar
ahora declara una variable de alcance dinámico, pero en general estoy bastante perdido. ¿Hay una buena explicación en alguna parte de las nuevas reglas de alcance de Emacs 24? O dicho de otra manera, cuando veo una variable en el código Emacs Lisp escrito para Emacs 24, ¿cómo puedo saber qué alcance está usando esa variable?
Digamos que algo de código se está evaluando paso a paso en Emacs (ya sea porque acaba de hacer Cx Ce
o porque se está cargando un archivo de Emacs Lisp o porque se está ejecutando una función desde un gancho, etc.), y que Emacs está a punto de Evalúa my-abc
dentro de ese código. Quizás my-abc
sea una variable local en ese código o tal vez no esté declarado o quizás tenga algún valor global, etc. De todos modos, el paso actual es la evaluación de my-abc
. En ese momento, Emacs verifica solo dos cosas para decidir si evaluar my-abc
con o sin alcance léxico.
Lo primero que comprueba Emacs es "¿es my-abc
una variable especial?". La respuesta a esa pregunta es sí si (defvar my-abc ...)
o (defcustom my-abc ..)
o etc se ejecutaron en algún momento en el pasado. Tal vez (defcustom my-abc ..)
se ejecutó al cargar algún otro archivo de Emacs Lisp, o tal vez evaluó algún código que contenga (defvar my-abc ...)
en el búfer de scratch, o tal vez no. Si la respuesta es sí por cualquier motivo, Emacs en este punto evaluará my-abc
utilizando el alcance dinámico.
Si la respuesta es no, Emacs verifica la segunda cosa, que es (A) "¿dónde está este código (que contiene el uso de my-abc
) que yo (Emacs) estoy revisando?". Esto no es (B) "¿cuál es el búfer actual ahora?". Si solo presionó Cx Ce en un búfer, diga foo.el
, y si la expresión que presionó Cx ce en contenía una llamada a una función llamada mah-hello
que se define en mah-stuff.el
, y si mah-hello
funciona el cuerpo contenía una llamada a una función llamada my-hello
que se define en my-stuff.el
, y si el cuerpo de la función de my-hello
contenía el uso de una variable llamada my-abc
, entonces, cuando Emacs finalmente ejecute my-hello
y luego está a punto de evaluar my-abc
allí, en el momento en que Emacs hace la pregunta A, responde my-stuff.el
a sí mismo. No es el buffer foo.el
que contiene la expresión inicial.
Entonces Emacs pregunta "es my-stuff.el
un búfer de ámbito léxico, en otras palabras, ¿es verdadero el lexical-binding
en ese búfer?". En caso afirmativo, Emacs evalúa my-abc
utilizando el alcance léxico, de lo contrario, utiliza el alcance dinámico.
Algunas actualizaciones: Además, cuando el código se cita como datos y luego se pasa a la función eval
, la respuesta a (A) no será un búfer. Aún así, es como si eval
crea un búfer imaginario para colocar el código y establecer el valor local de búfer de lexical-binding
para ese búfer en el segundo argumento pasado a eval
. La respuesta a (A) no es el búfer que contiene la llamada `eval ''. Es el búfer imaginario.
Para las macros de Lisp, cuando se está ejecutando algún código expandido por macro, es como si el código expandido se escribiera en el búfer que contiene el código que invocó la macro. Por lo tanto, la respuesta a (A) en este caso no es el búfer que definió la macro, sino el búfer donde reside el código que llamó a la macro.
El manual es la fuente definitiva. Empieza aqui:
Ch i g (elisp) Variable Scoping
RET
Originalmente había citado el manual en esta respuesta, pero esa información (que se remonta a Emacs 24.0.90.1) estaba un poco desactualizada. Es mejor leer el manual desde el interior de Emacs para que la información sea correcta para la versión que está utilizando.
Si en particular desea leerlo en una página web, la versión actual es:
http://www.gnu.org/software/emacs/manual/html_node/elisp/Variable-Scoping.html