Como funciona o escopo no emacs lisp

Oct 07 2020

Muitas configurações emacs compartilhadas publicamente têm este formato:

;; 01-something.el
(provide 'something)

;; init.el
(require 'something)

Suponha que eu esteja escrevendo um defun chamado "s-join" dentro de 01-something.el

Suponha que em algum lugar durante a inicialização init.el, magit.el carregue s.el- o popular pacote de utilitário de string, que também tem um defun chamado "s-join"

Então agora, em qualquer contexto, como sei o que é executado quando faço

(s-join)

?

Respostas

5 db48x Oct 07 2020 at 20:52

Todas as funções e variáveis ​​definidas em um arquivo que é carregado são colocadas no ambiente global. Embora o Emacs tenha pacotes instaláveis, esses pacotes não são isolados uns dos outros de forma alguma. Se dois arquivos definem funções ou variáveis ​​com o mesmo nome, você receberá um aviso quando o segundo for carregado.

Você pode descobrir onde uma função foi definida pedindo ajuda sobre a função com C-h f. Ele solicitará um nome de função. Se o texto em questão parecer um identificador lisp válido e existir uma função com esse nome, esse identificador será o valor padrão para o prompt. C-h vfará o mesmo para as variáveis. C-h Fsolicita um nome de função e leva você para a página de informações onde essa função está documentada, que pode incluir informações mais detalhadas.

1 jue Oct 08 2020 at 03:34

No Elisp, todos os nomes de funções normalmente (mas não necessariamente) residem como uma entrada em um ambiente global (obarray). No Elisp, as funções podem ser redefinidas. O que significa que a definição de função que foi avaliada (ou carregada) por último será a única conhecida e usada.

Desta forma, você pode alterar as funções em seu arquivo init, você só precisa ter certeza de que a definição de sua função é avaliada após a função que deseja alterar.

Mas cuidado! Se a função original muda no comportamento ou nos parâmetros, a sua não muda automaticamente e, portanto, as funções dependentes podem falhar ou se comportar mal.


Respondendo aos comentários abaixo, sobre como evitar a falha no uso do código-fonte.

  1. você deve escolher um nome de função que seja exclusivo para sua própria função para evitar isso (ou seja, prefixar o nome de sua função)
  2. você poderia escrever um guarda em torno de sua função, para evitar que sua definição de função substitua alguma função existente (isso não ajuda se sua função for substituída, consulte o próximo ponto)
(unless (fboundp 's-join)
  (defun s-join ()
    ...))
  1. você pode usar um adviceem sua função e verificar as características de sua função (ou seja, parâmetros ou primeiro sexo no corpo, etc.). Os avisos da IMO permanecem inalterados mesmo quando a função é redefinida.
1 PhilHudson Oct 14 2020 at 04:47

OP parece estar perdendo o ponto já claramente definido nas duas respostas dadas: você não pode fazer o que está pedindo. O Emacs usa uma convenção de nomenclatura voluntária, não regras de sintaxe ou compilação, para definir os namespaces. Pode parecer uma receita para o caos, mas na prática funciona muito bem.

O que você está fazendo ao nomear sua função s-joiné (efetivamente) roubar o sprefixo de identificação do namespace do pacote, violando a convenção. Não faça isso. Nomeie sua função anw/join-stringsou algo semelhante, conforme sugerido acima.

Se você realmente precisa substituir temporariamente uma função existente, pode usar cl-fletou cl-labels. Consulte o nó Info para o pacote CL.