Je ne suis pas tout à fait clair sur toutes les variations des variables locales du tampon, même après avoir lu tous les documents et un tas de publications ici sur SX.
Voici un résumé de mes compréhensions:
(defvar foo ..)
déclare une variable dynamique pour le fichier. Mais la variable n'est (1) pas connue des autres fichiers à moins qu'ils n'incluent également une defvar
instruction, et (2) la variable a une portée globale, pas un tampon local.
(make-variable-buffer-local foo)
après ce qui defvar
précède, il indique au compilateur et à tous les autres que la variable foo doit être traitée comme tampon local partout où elle est définie, lorsqu'elle est définie. Ce modèle est donc un bon style pour déclarer une variable locale de tampon, en mettant les deux instructions dos à dos dans le fichier.
(defvar xxx ...) ;declare xxx with global scope
(make-variable-buffer-local 'xxx) ;but now make it buffer-local everywhere
Pour plus de commodité, le (defvar-local xxx ...)
formulaire peut être utilisé sur une seule ligne, à la place des deux lignes ci-dessus:
(defvar-local xxx ...) ;make xxx buffer local everywhere
Une fois déclarée comme ci-dessus, la variable xxx peut être utilisée comme n'importe quelle autre variable dans les instructions setq.
Si je veux juste avoir une seule instance d'une variable tampon locale qui est déjà une variable dynamique globale, j'utiliserais les déclarations suivantes. La première déclare la variable dynamique de portée globale, et la deuxième instruction crée une seule instance d'une version tampon locale de cette variable, dans le tampon actuel:
(defvar xxx ...) ;declare xxx with global scope
(make-local-variable 'xxx) ;make xxx local in this buffer only
Maintenant pour mes questions explicites (toutes les questions ci-dessus étaient des questions implicites pour savoir si ma compréhension est correcte).
Lors de la définition de la valeur des variables, je peux utiliser setq
ou
setq-local
. Quand faut- setq-local
il l'utiliser? Pourquoi?
Que se passe-t-il si j'utilise setq-local
des vars tampons locaux ou des vars non tampons locaux?
Est setq-local
requis pour une defvar-local
variable déclarée?
Est-ce setq-local
qu'une defvar
variable déclarée normale la transformera en une variable locale tampon? (En d'autres termes, est-ce en setq-local
quelque sorte l'équivalent d'une (make-variable-local xxx)
déclaration?
(setq-local VAR VALUE)
est juste un raccourci pour(set (make-local-variable VAR) VALUE)
, qui était (et est toujours) un idiome commun.Réponses:
La plupart de vos hypothèses sont proches. J'en mentionnerai quelques-uns plus tard. Mais, d'abord la question principale.
Le formulaire
setq-local
est simplement une commodité, c'est la même chose que fairemake-local-variable
suivi desetq
. Si vous aviez fait un C-h f setq-localpour voir la documentation et cliqué sur la source, vous avez peut-être vu cela. C'est ainsi que j'ai vérifié ma première impression. Le code est un peu obscur, cependant, car il optimise des choses comme le fait qu'ilmake-local-variable
retourne réellement la variable elle-même. L'utilisationsetq-local
est un moyen de souligner le caractère local d'un code, afin que d'autres sachent que le code ne peut pas jouer avec la valeur globale de la variable. Vous n'avez pas besoin de l'utiliser pour accéder aux variables locales. N'importe quelle variable peut être mise en mémoire tampon locale et cela affectera tout le code qui touche la variable (sauf s'il fait tout son possible pour obtenir la copie globale avecsetq-default
ou similaire).Voilà la réponse principale. Maintenant, il y a quelques choses dans votre fond qui sont un peu décalées. Puisque vous avez posé des questions à ce sujet, je vais aborder certaines choses.
Le premier est "inconnu des autres fichiers". Ce n'est pas vraiment vrai. Tout code peut référencer n'importe quelle variable globale (c'est pourquoi elles sont appelées "globales") sans inclure le
defvar
(et le C-h f defvardit). En fait, il ne devrait y avoir qu'un seul maindefvar
(avec docstring et valeur par défaut) pour chaque variable globale. Undefvar
avec juste le nom de la variable peut être utilisé pour supprimer un avertissement du compilateur d'octets. Emacs utilise uniquement la valeur du premier qu'il voit¹ et la docstring du dernier. S'il y a plusieursdefvar
s avec valeur / docstring, ils peuvent être déroutants pour les personnes qui lisent le code. Et l'ordre de chargement des fichiers importera.Certaines variables sont destinées à être utilisées uniquement en tant que tampon local et ce sont celles qui utilisent
defvar-local
(ou les deux partiesdefvar
/ pourmake-variable-buffer-local
lesquelles il est abrégé, principalement dans un code plus ancien avant l'ajout de la forme courte). Cela en fait un tampon local dans tous les tampons. Pour certaines variables, leur utilisation principale n'est pas locale au tampon, mais pour une raison quelconque, vous souhaiterez peut-être qu'un tampon ait une valeur différente. C'est à ce moment que vous utilisezmake-local-variable
, généralement dans un code de configuration de tampon presque jamais juste après adefvar
.Et en général, les
defvar
formulaires ont deux objectifs . La première consiste à avoir une documentation, qui C-h vpeut être utilisée par d'autres pour savoir à quoi sert la variable. La seconde consiste à déclarer une valeur "par défaut", afin que la variable soit toujours définie. La déclaration de la valeur par défaut affecte uniquement l'instance globale (ou par défaut) d'une variable et n'est utilisée que si cette instance n'est pas déjà définie sur quelque chose. Cela signifie que si vous avezsetq
une variable et que vous incluez ensuite le fichier avecdefvar
(par exemple via arequire
), le defvar ne changera pas la valeur.¹ Plus précisément,
defvar
ne modifie pas la valeur de la variable si elle est déjà définie (elle définit cependant la docstring); cela signifie que le fichier init de l'utilisateur peut faire(setq some-variable)
avant le chargement d'un package pour remplacer la valeur par défaut du package.la source
set-local
dit aux lecteurs qu'une variable locale est définie. Tout ce que je peux faire pour améliorer la lisibilité de mon code est bon! PS. J'essaierai de cliquer sur la source plus souvent; à mon niveau de développement actuel, ça n'entre pas vraiment dans la sémantique ... :-)defvar
pour chaque variable globale" n'est pas strictement correct - il y a des situations où(defvar VARNAME)
sans valeur doit être déclarée, indépendamment de la bonne définition (avec la valeur initiale et idéalement une docstring) de ce VARNAME.setq-local
etdefvar-local
n'ont été introduits que dans Emacs 24.3.(defvar varname)
doivent être déclarées sans valeur? Je pense que c'est ce que Drew a suggéré dans un autre fil quand je demandais comment se débarrasser des avertissements de variables gratuits dans mes fichiers pour les globaux que j'avais déclarés ailleurs. Je fais ça maintenant. Est-ce la situation dont vous parlez?C-h i g (elisp) Warning Tips
). L'autre est pour les bibliothèques utilisant la liaison lexicale, pour garantir (si nécessaire) qu'une variable est liée dynamiquement plutôt que liée lexicalement.