Les macros sont-elles développées lors de la compilation du fichier?

13

J'ai une macro qui doit être développée à chaque instance de son utilisation lors de la compilation. Existe-t-il un moyen de le spécifier sans passer par la base de code et en emballant soigneusement chaque appel eval-when-compile?

Sean Allred
la source

Réponses:

13

Toutes les macros accessibles par le compilateur d'octets sont développées pendant la compilation. "Accessible" signifie essentiellement ne pas être cité.

Les corps de defuns, defmacros, lambdas sont tous compilés en octets lorsque le fichier source qui les contient est compilé en octets. Donc oui, toute macro à l'intérieur sera développée, tant qu'elle ne se trouve pas dans un quote ( '). Une erreur très courante est de mettre des lambdas dans une citation et, en fait, c'est pourquoi vous nelambda devriez jamais citer vos s .

C'est l'un des gros avantages des macros, tant qu'elles sont bien écrites, elles n'ont aucun impact sur les performances d'exécution. L'autre avantage est bien sûr leur puissance et leur polyvalence. L'inconvénient est que vous manipulez la syntaxe, pas les objets, donc il y a beaucoup de place pour les problèmes, certains inattendus, d'autres inévitables.

Malabarba
la source
7

Comme Malabarba l'a déjà expliqué, les macros sont développées lors de la compilation d'octets. Si un fichier n'est pas compilé, les macros sont développées lorsque le fichier est chargé (extension de macro désirée).

Mais ne vous fiez pas à cela. C'est un très mauvais style. Vous ne pouvez généralement pas vous attendre à ce que le code qui utilise votre macro soit réellement compilé, et vous devez généralement exécuter le moins de code possible pendant la compilation. Plus précisément, utilisez les macros à peine et uniquement s'il n'y a pas d'autre moyen. En règle générale, n'utilisez les macros que pour la syntaxe et jamais pour la sémantique (ou la fonctionnalité).

Les macros sont une abstraction qui fuit. Leur expansion est codée en dur dans le code cible au moment de la compilation et ne peut pas être modifiée rétrospectivement. Le code cible dépend ensuite de l' implémentation spécifique de la macro au moment de l'expansion. Plus précisément, cela dépend de toutes les API internes utilisées dans le corps de la macro.

Par conséquent, vous ne pouvez modifier aucune de ces API, ni aucun élément sur lequel repose l'expansion de macro, sans casser le code qui a été compilé avec votre macro.

L'utilisation libérale des macros pour la fonctionnalité ouvre la voie à l'enfer des dépendances .

lunaryorn
la source
Très bons points à garder à l'esprit lors de l'écriture ou de l'utilisation de macros.
Sean Allred
"L'utilisation libérale des macros pour la fonctionnalité ouvre la voie à l'enfer de la dépendance." Jusqu'à il y a une semaine, package.el avait un bogue qui interrompait complètement l'installation du package dans des situations de dépendance de macro parfaitement légitimes.
Malabarba
@Malabarba Care pour fournir des détails?
lunaryorn
@lunaryorn Voilà . Petit problème désagréable.
Malabarba
1
@lunaryorn Je conviens que les macros sont dangereuses (je modifierai même ma réponse pour paraître moins louable :), mais je ne pense pas que ce bug en soit une instance spécifique. Ce bug a eu d'autres manifestations (moins aggravantes) qui n'impliquent pas du tout les macros. Cela a également causé des problèmes avec les dépendances de fonction.
Malabarba