No tengo muy claras todas las variaciones de las variables locales de búfer, incluso después de leer todo el documento y un montón de publicaciones aquí en SX.
Aquí hay un resumen de mis entendimientos:
(defvar foo ..)
declara una variable dinámica para el archivo. Pero la variable es (1) desconocida para otros archivos a menos que también incluyan una defvar
declaración, y (2) la variable tiene un alcance global, no un búfer local.
(make-variable-buffer-local foo)
después de lo defvar
anterior le dice al compilador y a todos los demás que la variable foo debe ser tratada como buffer-local en todos los lugares donde se establece, cuando se establece. Por lo tanto, este patrón es un buen estilo para declarar una variable local de búfer, colocando ambas declaraciones consecutivas en el archivo.
(defvar xxx ...) ;declare xxx with global scope
(make-variable-buffer-local 'xxx) ;but now make it buffer-local everywhere
Por conveniencia, el (defvar-local xxx ...)
formulario se puede usar como una línea, en lugar de las dos líneas anteriores:
(defvar-local xxx ...) ;make xxx buffer local everywhere
Una vez declarada como arriba, la variable xxx se puede usar como cualquier otra variable en las instrucciones setq.
Si solo quiero tener una sola instancia de una variable local de búfer que ya sea una variable dinámica global, usaría las siguientes declaraciones. La primera declara la variable dinámica de alcance global, y la segunda declaración hace solo una instancia de una versión local de búfer de esa variable, en el búfer actual:
(defvar xxx ...) ;declare xxx with global scope
(make-local-variable 'xxx) ;make xxx local in this buffer only
Ahora para mis preguntas explícitas (todo lo anterior fueron preguntas implícitas sobre si mi comprensión es correcta).
Al establecer el valor de las variables, puedo usar setq
o
setq-local
. ¿Cuándo se debe setq-local
usar? ¿Por qué?
¿Qué sucede si lo uso setq-local
en vars locales de búfer o vars no locales de búfer?
¿Se setq-local
requiere para una defvar-local
variable declarada?
¿ setq-local
En una defvar
variable declarada normal la convertirá en una variable local de búfer? (En otras palabras, ¿es de setq-local
alguna manera el equivalente de una (make-variable-local xxx)
declaración?
fuente
(setq-local VAR VALUE)
es solo una abreviatura de(set (make-local-variable VAR) VALUE)
, que era (y sigue siendo) un idioma común.Respuestas:
La mayoría de sus suposiciones son cercanas. Mencionaré algunos más tarde. Pero, primero la pregunta principal.
La forma
setq-local
es meramente una conveniencia, es lo mismo que hacermake-local-variable
seguido desetq
. Si hubiera hecho un C-h f setq-localpara ver la documentación y hecho clic en la fuente, es posible que haya visto esto. Así es como verifiqué mi primera impresión. Sin embargo, el código es un poco oscuro, ya que se está optimizando en cosas como el hecho de que enmake-local-variable
realidad devuelve la variable en sí. Usarsetq-local
es una forma de señalar la localidad en algunos códigos, para que otros sepan que el código no puede jugar con el valor global de la variable. Usted no necesita utilizarlo para acceder a las variables locales. Cualquier variable se puede hacer local en el búfer y eso afectará a todo el código que toca la variable (excepto si se sale de su camino para obtener la copia global consetq-default
o similar).Esa es la respuesta principal. Ahora, hay algunas cosas en su fondo que están un poco apagadas. Como me preguntaste sobre eso, abordaré algunas cosas.
El primero es "no conocido por otros archivos". Esto no es realmente cierto. Cualquier código puede hacer referencia a cualquier variable global (es por eso que se llaman "globales") sin incluir el
defvar
(y lo C-h f defvardice). De hecho, solo debe haber un maindefvar
(con docstring y valor predeterminado) para cada variable global. Sedefvar
puede usar un solo nombre de variable para suprimir una advertencia del compilador de bytes. Emacs solo usa el valor del primero que ve¹ y la cadena de documentos del último. Si hay variosdefvar
correos electrónicos con valor / cadena de documentación, pueden ser confusos para las personas que leen el código. Y el orden de carga de los archivos será importante.Algunas variables están destinadas a usarse solo como buffer local y esas son las que usan
defvar-local
(o las dos partesdefvar
/ paramake-variable-buffer-local
las que es corto, principalmente en código anterior antes de que se agregara el formulario corto). Esto hace que sea local en el búfer en todos los búferes. Para algunas variables, su uso principal no es local en el búfer, pero por alguna razón es posible que desee que un búfer tenga un valor diferente. Ahí es cuando lo usasmake-local-variable
, generalmente en algún código de configuración del búfer, casi nunca después de undefvar
.Y como una cosa general, los
defvar
formularios tienen dos propósitos . Una es tener alguna documentación, para que otros C-h vpuedan usarla para saber para qué sirve la variable. El segundo es declarar un valor "predeterminado", de modo que la variable siempre esté establecida. La declaración del valor predeterminado solo afecta a la instancia global (o predeterminada) de una variable, y solo se usa si esa instancia aún no está establecida en algo. Eso significa que sisetq
alguna variable y luego incluye el archivo condefvar
(por ejemplo, arequire
), el defvar no cambiará el valor.¹ Más precisamente,
defvar
no modifica el valor de la variable si ya está establecida (sin embargo, establece la cadena de documentación); esto está pensado para que el archivo init del usuario pueda hacerlo(setq some-variable)
antes de cargar un paquete para anular el valor predeterminado del paquete.fuente
set-local
le dice a los lectores que se está estableciendo una var local. ¡Todo lo que pueda hacer para mejorar la legibilidad de mi código es bueno! PD. Intentaré hacer clic en la fuente con más frecuencia; en mi nivel actual de desarrollo, a menudo no llega a la semántica ... :-)defvar
para cada variable global" no es estrictamente correcto: hay situaciones en las que se debe declarar(defvar VARNAME)
sin un valor, independientemente de la definición adecuada (con valor inicial e idealmente una cadena de documentos) de ese VARNAME.setq-local
ydefvar-local
solo se introdujeron en Emacs 24.3.(defvar varname)
deberían declararse sin valor? Estoy pensando que eso es lo que Drew sugirió en otro hilo cuando estaba preguntando cómo deshacerme de las advertencias de variables libres en mis archivos para los globales que había declarado en otro lugar. Hago eso ahora. ¿Es esa la situación de la que hablas?C-h i g (elisp) Warning Tips
). El otro es para las bibliotecas que usan enlace léxico, para asegurar (si es necesario) que una variable está unida dinámicamente en lugar de estar unida léxicamente.