Não sou muito claro sobre todas as variações de variáveis locais de buffer, mesmo depois de ler todo o documento e várias postagens aqui no SX.
Aqui está um resumo dos meus entendimentos:
(defvar foo ..)
declara uma variável dinâmica para o arquivo. Mas a variável (1) não é conhecida por outros arquivos, a menos que inclua também uma defvar
instrução e (2) a variável é de escopo global, não local de buffer.
(make-variable-buffer-local foo)
após o que foi defvar
dito acima, diz ao compilador e a todos os demais que a variável foo deve ser tratada como local do buffer em qualquer lugar em que for definida, quando for definida. Portanto, esse padrão é um bom estilo para declarar uma variável local de buffer, colocando as duas instruções consecutivas no arquivo.
(defvar xxx ...) ;declare xxx with global scope
(make-variable-buffer-local 'xxx) ;but now make it buffer-local everywhere
Por conveniência, o (defvar-local xxx ...)
formulário pode ser usado como uma linha, no lugar das duas linhas acima:
(defvar-local xxx ...) ;make xxx buffer local everywhere
Uma vez declarada como acima, a variável xxx pode ser usada como qualquer outra variável nas instruções setq.
Se eu apenas quero ter uma única instância de uma variável local buffer que já é uma variável dinâmica global, eu usaria as seguintes declarações. O primeiro declara a variável dinâmica de escopo global e a segunda instrução cria apenas uma instância de uma versão local do buffer dessa variável, no buffer atual:
(defvar xxx ...) ;declare xxx with global scope
(make-local-variable 'xxx) ;make xxx local in this buffer only
Agora, para minhas perguntas explícitas (todas as perguntas acima foram implícitas sobre se meu entendimento está correto).
Ao definir o valor das variáveis, posso usar setq
ou
setq-local
. Quando deve setq-local
ser usado? Por quê?
O que acontece se eu usar setq-local
em vars locais de buffer local ou vars não locais de buffer?
É setq-local
necessário para uma defvar-local
variável declarada?
Em setq-local
uma defvar
variável declarada normal , a transformará em uma variável local de buffer? (Em outras palavras, é de setq-local
alguma forma o equivalente a uma (make-variable-local xxx)
declaração?
fonte
(setq-local VAR VALUE)
é apenas uma abreviação de(set (make-local-variable VAR) VALUE)
, que era (e ainda é) um idioma comum.Respostas:
A maioria de suas suposições está próxima. Mencionarei alguns depois. Mas, primeiro a questão principal.
O formulário
setq-local
é apenas uma conveniência, é o mesmo que fazermake-local-variable
seguido porsetq
. Se você fez um C-h f setq-localpara ver a documentação e clicou na fonte, pode ter visto isso. Foi assim que verifiquei minha primeira impressão. O código é um pouco obscuro, porém, uma vez que está otimizando coisas como o fato demake-local-variable
realmente retornar a variável em si. Usarsetq-local
é uma maneira de apontar a localidade em algum código, para que outras pessoas saibam que o código não pode estar jogando com o valor global da variável. Você não precisa usá-lo para acessar variáveis locais. Qualquer variável pode ser feita como local do buffer e isso afetará todo o código que toca a variável (exceto se ela se esforçar para obter a cópia globalsetq-default
ou similar).Essa é a resposta principal. Agora, existem algumas coisas em seu histórico que estão um pouco fora. Desde que você perguntou sobre isso, vou abordar algumas coisas.
O primeiro é "desconhecido para outros arquivos". Isso não é verdade. Qualquer código pode fazer referência a qualquer variável global (é por isso que eles são chamados "globais") sem incluir o
defvar
(e C-h f defvardiz isso). De fato, deve haver apenas um principaldefvar
(com docstring e valor padrão) para cada variável global. Umdefvar
com apenas o nome da variável pode ser usado para suprimir um aviso do compilador de bytes. O Emacs usa apenas o valor do primeiro que ele vê¹ e a sequência de caracteres do último. Se houver váriosdefvar
s com valor / sequência de caracteres, eles podem ser confusos para as pessoas que leem o código. E a ordem de carregamento dos arquivos será importante.Algumas variáveis destinam - se a ser usadas apenas como local de buffer e essas são as que são usadas
defvar-local
(ou as duas partesdefvar
/ pelasmake-variable-buffer-local
quais é abreviada, principalmente no código antigo antes da adição do formulário abreviado). Isso faz com que seja local de buffer em todos os buffers. Para algumas variáveis, seu uso principal não é local do buffer, mas por algum motivo você pode desejar que um buffer tenha um valor diferente. É quando você usamake-local-variable
, geralmente em algum código de configuração do buffer quase nunca logo após adefvar
.E como uma coisa geral, existem dois propósitos para os
defvar
formulários. Uma é ter alguma documentação, para que C-h vpossa ser usada por outras pessoas para saber para que serve a variável. O segundo é declarar um valor "padrão", para que a variável seja sempre definida. A declaração do valor padrão afeta apenas a instância global (ou padrão) de uma variável e é usada apenas se essa instância ainda não estiver configurada para algo. Isso significa que se vocêsetq
incluir alguma variável e incluir o arquivo comdefvar
(por exemplo, arequire
), o defvar não alterará o valor.Precisely Mais precisamente,
defvar
não modifica o valor da variável se ela já estiver configurada (porém, ela define a doutrina); isso é feito para que o arquivo init do usuário possa executar(setq some-variable)
antes que um pacote seja carregado para substituir o valor padrão do pacote.fonte
set-local
informa aos leitores que um var local está sendo definido. Tudo o que posso fazer para melhorar a legibilidade do meu código é bom! PS. Vou tentar clicar na fonte com mais frequência; no meu nível atual de desenvolvimento, que muitas vezes não realmente chegar a semântica ... :-)defvar
para cada variável global" não está estritamente correto - há situações em que(defvar VARNAME)
sem um valor deve ser declarado, independentemente da definição adequada (com valor inicial e, idealmente, uma doutrina) desse VARNAME.setq-local
edefvar-local
só foram introduzidos no Emacs 24.3.(defvar varname)
deve ser declarado sem valor? Estou pensando que foi o que Drew sugeriu em outro tópico quando estava perguntando como se livrar de avisos de variáveis livres em meus arquivos para globais que eu havia declarado em outro lugar. Eu faço isso agora. É dessa situação que você fala?C-h i g (elisp) Warning Tips
). O outro é para bibliotecas que usam ligação lexical, para garantir (se necessário) que uma variável seja vinculada dinamicamente, e não lexicamente.