2008-11-11 12 views
5

Todavía luchando por comprender cuáles son las mejores prácticas con respecto a las macros. Estoy intentando escribir una macro que define paquetes sobre la marcha.Principiante en Common Lisp: Pregunta de macro para definir paquetes sobre la marcha

(defmacro def-dynamic-package (name) 
    `(defpackage ,(intern (string-upcase name) "KEYWORD") 
    (:use :common-lisp))) 

Esto funciona bien sólo para expresiones tales como:

(def-dynamic-package "helloworld") 

Pero fracasa miserablemente para algo como esto:

(defun make-package-from-path (path) 
    (def-dynamic-package (pathname-name path))) 

o

(defun make-package-from-path (path) 
    (let ((filename (pathname-path))) 
    (def-dynamic-package filename))) 

entiendo cómo la mayoría las macros básicas funcionan pero cómo para implementar esto se me escapa.

Respuesta

8

defpackage es un macro. Como tal, se expande en tiempo de compilación, no en tiempo de ejecución. Lo que desea es algo que se llama en tiempo de ejecución para crear un nuevo paquete. Por lo tanto, defpackage no puede hacer nada por usted.

Afortunadamente, también hay make-package, que proporciona defpackage 's características como una función. Úselo en lugar de defpackage.

+0

Ah, este fue uno de los problemas que tuve al diseñar una macro, que el desfase en sí mismo era una macro que me dificultaba razonar acerca de un buen enfoque. Gracias. – dnolen

+2

En realidad, es un paquete de desintegración que proporciona paquetes funciones como una práctica macro. :-) –

0

Se espera error aquí, porque se utiliza una macro cuando no se debe evaluar su argumento.

En su primera marca-paquete-de-camino, el def-dinámico-paquete recibirán como argumento una lista que es igual al valor de la siguiente expresión:

(list 'pathname-name 'path) 

En su caso, sólo quieren una función:

(defun def-dynamic-package (name) 
    (defpackage (string-upcase name) 
    (:use :common-lisp))) 

Por cierto, si marca la CLHS, verá que el primer argumento de defpackage no tiene que ser un símbolo, pero cualquier string designator.

+0

Muchas gracias, tuve la sensación de que aprender Common Lisp es mucho sobre aprender cuándo y cuándo no usar macros. – dnolen

+0

Lo que estás haciendo ahí es definir un paquete llamado "(STRING-NOMBRE DE UPCASE)" - al menos eso sería lo que estabas haciendo si una lista fuera un designador de cadena válido. En cualquier caso, su código no funciona de manera portátil. –

+0

Un par de cuestiones: a) def * generalmente nombra macros yb) vea la respuesta de Matthias donde menciona MAKE-PACKAGE. (Su función no funciona porque DEFPACKAGE no evalúa su primer argumento. –