As macros são expandidas quando o arquivo é compilado?

13

Eu tenho uma macro que precisa ser expandida a cada instância única de seu uso em tempo de compilação. Existe uma maneira de especificar isso sem passar pela base de código e encerrar cuidadosamente cada chamada eval-when-compile?

Sean Allred
fonte

Respostas:

13

Todas as macros acessíveis pelo compilador de bytes são expandidas durante a compilação. "Alcançável" significa essencialmente não ser citado.

O corpo de defuns, defmacros, lambdas é todo compilado em bytes quando o arquivo de origem que os contém é compilado em bytes. Portanto, sim, qualquer macro dentro deles será expandida, desde que não esteja dentro de uma citação ( '). Um erro muito comum é envolver lambdas em uma citação e, de fato, é por isso que você nuncalambda deve citar seus s .

Essa é uma das grandes vantagens das macros, desde que sejam bem escritas e não tenham impacto no desempenho do tempo de execução. A outra vantagem é seu poder e versatilidade, é claro. A desvantagem é que você está manipulando a sintaxe, não os objetos, portanto há muito espaço para problemas, alguns inesperados, outros inevitáveis.

Malabarba
fonte
7

Como Malabarba já explicou, as macros são expandidas durante a compilação de bytes. Se um arquivo não for compilado, as macros serão expandidas quando o arquivo for carregado (expansão rápida da macro).

Não confie nisso, no entanto. É um estilo muito ruim. Geralmente, você não pode esperar que o código que usa sua macro seja realmente compilado e, geralmente, você deve executar o mínimo de código possível durante a compilação. Especificamente, use macros apenas e apenas se não houver outra maneira. Como regra geral, use macros apenas para sintaxe e nunca para semântica (ou funcionalidade).

Macros são uma abstração com vazamento. Sua expansão é codificada no código de destino no momento da compilação e não pode ser alterada retrospectivamente. O código de destino posteriormente depende da implementação específica da macro no momento da expansão. Especificamente, depende de toda a API interna usada no corpo da macro.

Conseqüentemente, você não pode alterar nada dessa API ou qualquer coisa em que a expansão da macro dependa, sem quebrar nenhum código compilado na sua macro.

O uso liberal de macros para funcionalidade abre o caminho para o inferno da dependência .

lunaryorn
fonte
Muito bons pontos a serem lembrados ao escrever ou usar macros.
Sean Allred
"O uso liberal de macros para funcionalidade abre o caminho para o inferno da dependência." Até uma semana atrás, o package.el tinha um bug que interrompia completamente a instalação do pacote em situações de dependência de macro perfeitamente legítimas.
Malabarba
@ Malabarba Care para fornecer detalhes?
lunaryorn
@lunaryorn Aqui você vai . Problema desagradável.
Malabarba
1
@ lunaryorn Concordo que macros são perigosas (vou editar minha resposta para parecer menos elogiosa :), mas não acho que esse bug tenha sido uma instância específica dele. Esse bug tinha outras manifestações (menos agravantes) que não envolvem macros. Também causou problemas com dependências de função.
Malabarba