Emacs LispGenericName
Emacs Lisp é um dialeto da linguagem de programação Lisp usada como linguagem de script pelo Emacs (uma família de editores de texto mais comumente associada ao GNU Emacs e XEmacs). Ele é usado para implementar a maior parte da funcionalidade de edição incorporada ao Emacs, sendo o restante escrito em C, assim como o interpretador Lisp. O Emacs Lisp também é denominado Elisp, embora também exista um dialeto Lisp mais antigo e não relacionado com esse nome.
Os usuários do Emacs geralmente escrevem o código Emacs Lisp para personalizar e estender o Emacs. Outras opções incluem o recurso Customize que está no GNU Emacs desde a versão 20. Ele mesmo escrito em Emacs Lisp, Customize fornece um conjunto de páginas de preferências que permitem ao usuário definir opções e visualizar seus efeitos em a sessão do Emacs em execução. Quando o usuário salva suas alterações, o Customize simplesmente grava o código Emacs Lisp necessário no arquivo de configuração do usuário, que pode ser definido como um arquivo especial que apenas o Customize usa, para evitar a possibilidade de alterar as configurações do usuário. próprio arquivo.
O Emacs Lisp também pode funcionar como uma linguagem de script, muito parecido com o Unix Bourne shell ou Perl, chamando o Emacs no modo batch. Desta forma, pode ser chamado a partir da linha de comando ou através de um arquivo executável, e suas funções de edição, como buffers e comandos de movimento, estão disponíveis para o programa exatamente como no modo normal. Nenhuma interface de usuário é apresentada quando o Emacs é iniciado no modo batch; ele simplesmente executa o script passado e sai, exibindo qualquer saída do script.
Comparado com outros dialetos Lisp
O Emacs Lisp é o mais próximo do Maclisp, com alguma influência posterior do Common Lisp. Suporta métodos de programação imperativos e funcionais. Richard Stallman escolheu Lisp como a linguagem de extensão para sua reescrita do Emacs (o original usava o Text Editor and Corrector (TECO) como sua linguagem de extensão) por causa de seus recursos poderosos, incluindo a capacidade de tratar funções como dados. Embora o padrão Common Lisp ainda não tivesse sido formulado, o Scheme existia na época em que Stallman estava reescrevendo o Gosling Emacs no GNU Emacs. Ele optou por não usá-lo por causa de seu desempenho comparativamente ruim em estações de trabalho (em oposição aos minicomputadores que eram a casa tradicional do Emacs) e queria desenvolver um dialeto que achava que seria mais facilmente otimizado.
O dialeto Lisp usado no Emacs difere substancialmente dos dialetos Common Lisp e Scheme mais modernos usados para programação de aplicativos. Uma característica proeminente do Emacs Lisp está no uso de escopo dinâmico em vez de léxico por padrão. Ou seja, uma função pode fazer referência a variáveis locais no escopo de onde é chamada, mas não no escopo em que foi definida. Recentemente, houve um esforço contínuo para atualizar o código para usar o escopo léxico, pelos motivos descritos abaixo.
1955 | 1960 | 1965 | 1970 | 1975 | 1980 | 1985 | 1990 | 1995 | 2000 | 2005 | 2010 | 2015 | 2020 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
LISP 1, 1.5, LISP 2 (abandonado) | ||||||||||||||
Maclisp | ||||||||||||||
Interlisação | ||||||||||||||
MDL | ||||||||||||||
Máquina de Lisp | ||||||||||||||
Esquema | R5RS | R6RS | R7RS pequeno | |||||||||||
NIL | ||||||||||||||
ZIL (Língua de Implementação de Zork) | ||||||||||||||
Franz Lisp | ||||||||||||||
Lisp comum | Padrão ANSI | |||||||||||||
Le Lisp | ||||||||||||||
MIT Esquema | ||||||||||||||
T | ||||||||||||||
Chez Scheme | ||||||||||||||
Emacs Lisp | ||||||||||||||
AutoLISP | ||||||||||||||
Pico Lisp | ||||||||||||||
Gambito | ||||||||||||||
Eu... | ||||||||||||||
ISLISP | ||||||||||||||
Abre a porta. | ||||||||||||||
PLT Esquema | Racket | |||||||||||||
GNU Guile | ||||||||||||||
Visual LISP | ||||||||||||||
Clojure | ||||||||||||||
Arco | ||||||||||||||
LFE | ||||||||||||||
Hy |
Exemplo
Para entender a lógica por trás do Emacs Lisp, é importante lembrar que há uma ênfase em fornecer estruturas de dados e recursos específicos para criar um editor de texto versátil em vez de implementar uma linguagem de programação de uso geral. Por exemplo, o Emacs Lisp não pode ler facilmente um arquivo uma linha por vez - o arquivo inteiro deve ser lido em um buffer do Emacs. No entanto, o Emacs Lisp fornece muitos recursos para navegar e modificar o texto do buffer em uma frase, parágrafo ou nível sintático superior, conforme definido pelos modos.
Aqui segue um exemplo simples de uma extensão Emacs escrita em Emacs Lisp. No Emacs, a área de edição pode ser dividida em áreas separadas chamadas janelas, cada uma exibindo um buffer diferente. Um buffer é uma região de texto carregada no Emacs' memória (possivelmente de um arquivo) que pode ser salvo em um documento de texto.
Os usuários podem pressionar a tecla padrão C-x 2 para abrir uma nova janela. Isso executa a função Emacs Lisp split-window-below
. Normalmente, quando a nova janela aparece, ela exibe o mesmo buffer da anterior. Suponha que desejamos fazer com que ele exiba o próximo buffer disponível. Para fazer isso, o usuário escreve o seguinte código Emacs Lisp, em um arquivo de origem Emacs Lisp existente ou em um buffer Emacs vazio:
(defuntos meu-split-window-func () (interativo) (split-window-below) (set-window-buffer (próxima janela) (outro buffer)(global-set-key (- Sim. "C-x 2") # 'meu-split-window-func)
A primeira instrução, (defun...)
, define uma nova função, my-split-window-func
, que chama split-window- abaixo
(a antiga função de divisão de janela), então informa a nova janela para exibir outro (novo) buffer. A segunda instrução, (global-set-key...)
religa a sequência de teclas "C-x 2" à nova função.
Isso também pode ser escrito usando o recurso chamado advice, que permite ao usuário criar wrappers em torno de funções existentes em vez de definir suas próprias. Isso tem a vantagem de não exigir que as combinações de teclas sejam alteradas e de funcionar onde quer que a função original seja chamada, além de ser mais simples de escrever, mas a desvantagem de tornar a depuração mais complicada. Por esta razão, aconselhamento não é permitido no código-fonte do GNU Emacs, mas se o usuário desejar, o recurso de aconselhamento pode ser usado em seu código para reimplementar o código acima da seguinte forma:
(O que fazer? split-window-below (depois meu-janeiro-splitting-dispositivo Primeiro primeiro. () Ative a ativação) (set-window-buffer (próxima janela) (outro buffer)
Isso instrui split-window-below
a executar o código fornecido pelo usuário sempre que for chamado, após executar o restante da função. O conselho também pode ser especificado para executar antes da função original, ao redor dela (literalmente envolvendo o original) ou para executar condicionalmente a função original com base nos resultados do conselho.
O Emacs 24.4 substitui esse mecanismo defadvice
por advice-add
, que é considerado mais flexível e simples. O conselho acima pode ser reimplementado usando o novo sistema como:
(defuntos switch-to-next-window-in-split () (set-window-buffer (próxima janela) (outro buffer)(aconselhamento "Split-window-below" : antes # 'switch-to-next-window-in-split)
Essas alterações entram em vigor assim que o código é avaliado. Não é necessário recompilar, reiniciar o Emacs ou mesmo refazer um arquivo de configuração. Se o código for salvo em um arquivo init do Emacs, o Emacs carregará a extensão na próxima vez que for iniciado. Caso contrário, as alterações devem ser reavaliadas manualmente quando o Emacs for reiniciado.
Código-fonte
O código Emacs Lisp é armazenado em sistemas de arquivos como arquivos de texto simples, por convenção com o sufixo de nome de arquivo ".el
". O arquivo init do usuário é uma exceção, geralmente aparecendo como ".emacs
" apesar de ser avaliado como qualquer código Emacs Lisp. Desde meados da década de 1990, o Emacs também carrega ~/.emacs.el
e ~/.emacs.d/init.el
. Além disso, os usuários podem especificar qualquer arquivo para carregar como um arquivo de configuração na linha de comando ou declarar explicitamente que nenhum arquivo de configuração deve ser carregado. Quando os arquivos são carregados, um componente interpretador do programa Emacs lê e analisa as funções e variáveis, armazenando-as na memória. Eles ficam disponíveis para outras funções de edição e para comandos do usuário. Funções e variáveis podem ser livremente modificadas e redefinidas sem reiniciar o editor ou recarregar o arquivo de configuração.
Para economizar tempo e espaço de memória, muitas das funcionalidades do Emacs são carregadas apenas quando necessário. Cada conjunto de recursos opcionais fornecidos com o Emacs é implementado por uma coleção de códigos do Emacs chamada de pacote ou biblioteca. Por exemplo, existe uma biblioteca para destacar palavras-chave no código-fonte do programa e uma biblioteca para jogar Tetris. Cada biblioteca é implementada usando um ou mais arquivos de origem Emacs Lisp. As bibliotecas podem definir um ou mais modos principais para ativar e controlar sua função.
Os desenvolvedores do Emacs escrevem certas funções em C. Elas são primitivas, também denominadas funções internas ou subrs. Embora as primitivas possam ser chamadas a partir do código Lisp, elas só podem ser modificadas editando os arquivos de origem C e recompilando. No GNU Emacs, as primitivas não estão disponíveis como bibliotecas externas; eles fazem parte do executável do Emacs. No XEmacs, o carregamento em tempo de execução dessas primitivas é possível, usando o suporte do sistema operacional para vinculação dinâmica. As funções podem ser escritas como primitivas porque precisam de acesso a dados externos e bibliotecas não disponíveis no Emacs Lisp, ou porque são chamadas com frequência suficiente para que a velocidade comparativa de C versus Emacs Lisp faça uma diferença valiosa.
No entanto, como os erros no código C podem facilmente levar a violações de segmentação ou a bugs mais sutis, que travam o editor, e porque escrever código C que interage corretamente com o coletor de lixo do Emacs Lisp é propenso a erros, o número de funções implementadas como primitivas são mantidas em um mínimo necessário.
Código de bytes
Acompilação de bytes pode fazer com que o código Emacs Lisp seja executado mais rapidamente. O Emacs contém um compilador que pode traduzir os arquivos fonte do Emacs Lisp em uma representação especial denominada bytecode. Os arquivos de bytecode do Emacs Lisp têm o sufixo de nome de arquivo ".elc
". Em comparação com os arquivos de origem, os arquivos bytecode carregam mais rapidamente, ocupam menos espaço no disco, usam menos memória quando carregados e são executados mais rapidamente.
O bytecode ainda roda mais lentamente que os primitivos, mas as funções carregadas como bytecode podem ser facilmente modificadas e recarregadas. Além disso, os arquivos bytecode são independentes de plataforma. O código Emacs Lisp padrão distribuído com o Emacs é carregado como bytecode, embora os arquivos de origem correspondentes também sejam fornecidos para referência do usuário. As extensões fornecidas pelo usuário normalmente não são compiladas por byte, pois não são tão grandes nem computacionalmente intensivas.
Recursos de linguagem
Notavelmente, o "cl-lib" pacote implementa um subconjunto razoavelmente grande de Common Lisp. Este pacote substitui um "cl" pacote, que substituiria as definições de funções existentes do Emacs Lisp por outras mais semelhantes às encontradas no Common Lisp. A opção "cl-lib" pacote, por outro lado, segue as diretrizes de estilo Emacs Lisp mais de perto e prefixa cada função e macro que define com "cl-" (por exemplo, cl-defun
, que não entra em conflito com o nome do defun
integrado), evitando as mudanças inesperadas no comportamento que podem ocorrer sempre que o "cl" pacote foi carregado.
O Emacs Lisp (ao contrário de algumas outras implementações do Lisp) não faz otimização de chamada final. Sem isso, as recursões de cauda podem eventualmente levar ao estouro da pilha.
A biblioteca apel auxilia na escrita de código Emacs Lisp portátil, com a ajuda da ponte da plataforma polysylabi.
O Emacs Lisp é um Lisp-2 como o Common Lisp, o que significa que ele possui um namespace de função separado do namespace que ele usa para outras variáveis.
Do escopo dinâmico ao léxico
Assim como o MacLisp, o Emacs Lisp usa escopo dinâmico, oferecendo estático (ou lexical) como opção a partir da versão 24. Ele pode ser ativado configurando a variável local do arquivo lexical-binding
. Antes dessa opção ser adicionada, era possível usar a macro lexical-let
do (agora obsoleto) "cl" pacote para fornecer escopo lexical eficaz.
No escopo dinâmico, se um programador declara uma variável dentro do escopo de uma função, ela fica disponível para sub-rotinas chamadas dentro dessa função. Originalmente, isso pretendia ser uma otimização; o escopo lexical ainda era incomum e de desempenho incerto. "Perguntei ao RMS quando ele estava implementando o emacs lisp por que o escopo era dinamicamente e sua resposta exata foi que o escopo léxico era muito ineficiente." O escopo dinâmico também foi criado para fornecer maior flexibilidade para personalizações do usuário. No entanto, o escopo dinâmico tem várias desvantagens. Em primeiro lugar, pode facilmente levar a erros em programas grandes, devido a interações não intencionais entre variáveis em diferentes funções. Em segundo lugar, acessar variáveis sob escopo dinâmico geralmente é mais lento do que sob escopo léxico.
Contenido relacionado
Teclado
ABM
Liga