2015-03-17 1 views
2

Les macros peuvent créer des fonctions dans la portée globale. Par exemple:Fonctions prédéfinies générées automatiquement avec les macros Common Lisp

(defmacro test-macro (&body functions) 
`(progn ,@(loop for function in functions 
       collect `(defun ,function() 
          *some-interesting-thing*)))) 

Un autre exemple (quoique avec des méthodes) serait les accesseurs générés automatiquement pour une classe CLOS.

Les fonctions ne sont pas définies au moment de l'expansion de la macro, mais plutôt lorsque le code généré est compilé/interprété. Cela peut causer quelques difficultés. Si ces fonctions sont attendues, un avertissement sera émis. Quelle est la manière idiomatique de définir ces fonctions avant qu'elles ne soient correctement définies? Une solution possible pourrait être la suivante:

(defmacro test-macro (&body functions) 
    (macrolet ((empty-function (name) 
       `(defun ,name()))) 
    (dolist (function functions) 
     (empty-function function))) 
    `(progn ,@(loop for function in functions 
       collect `(defun ,function() 
          *some-interesting-thing*)))) 

Notez que la fonction intermédiaire est définie au cours du temps d'expansion macro.

+0

Le problème que vous décrivez (tel que je le comprends) ne devrait pas exister (selon la spécification) et n'existe pas (dans toute application que je connais). Pourriez-vous s'il vous plaît fournir des exemples de code explicites? – sds

Répondre

4

Si vous devez définir une fonction au moment de la compilation sur le premier niveau, puis utilisez:

(eval-when (:compile-toplevel) 
    (defun foo ...)) 

Notez que vous pouvez définir une macro qui génère un tel code. Une telle forme peut faire partie d'un PROGN.

+0

Dans la majorité des cas, si vous utilisez 'eval-when' au niveau supérieur, vous voulez tout' ((: compile-toplevel: load-toplevel: execute) '. – Svante

+0

@Svante: Je ne dirais pas ça. Les implémentations Common Lisp utilisent souvent ': compile-toplevel' pour les effets secondaires lors de la compilation. Par exemple 'DEFUN' note la fonction à la compilation, mais ne la définit pas. Souvent, c'est un modèle utile à suivre. Aussi 'eval-when' ne fait que du sens au soi-disant toplevel. A part cela, il n'a pas d'utilisation réelle. Notez que 'toplevel' a une signification spéciale dans le contexte de la compilation et que les formes à l'intérieur d'un 'PROGN' sont toujours à 'toplevel'. –