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
?
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
?
Respostas:
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 defun
s, defmacro
s, lambda
s é 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 lambda
s 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.
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 .