2008-11-11 2 views
5

Immer noch zu kämpfen, um zu verstehen, welche Best Practices in Bezug auf Makros sind. Ich versuche, ein Makro zu schreiben, das Pakete on-the-fly definiert.Anfänger bei Common Lisp: Makro-Frage zum Definieren von Paketen im Flug

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

Dies funktioniert für Ausdrücke nur fein wie:

(def-dynamic-package "helloworld") 

aber scheitert kläglich dies so etwas wie:

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

oder

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

Ich verstehe, wie die meisten grundlegende Makros funktionieren aber wie um dies zu implementieren, entkommt mir.

Antwort

8

defpackage ist ein Makro. Daher wird es zur Kompilierungszeit und nicht zur Laufzeit erweitert. Was Sie wollen, ist etwas, das zur Laufzeit aufgerufen wird, um ein neues Paket zu erstellen. Daher kann defpackage nichts für Sie tun.

Glücklicherweise gibt es auch make-package, die defpackage ‚s Eigenschaften als Funktion zur Verfügung stellt. Verwenden Sie es anstelle von defpackage.

+0

Ah, das war eines der Probleme, die ich hatte, ein Makro zu entwerfen, das defpackage selbst war ein Makro machte es mir schwer, über einen guten Ansatz zu begründen. Danke. – dnolen

+2

Eigentlich ist es defpackage, das make-package Features als handliches Makro. :-) –

0

Hier ist ein Fehler zu erwarten, da ein Makro verwendet wird, wenn sein Argument nicht ausgewertet werden soll.

In Ihrem ersten Make-Paket-von-Weg, der def-Dynamic-Paket wird eine Liste als Argument erhalten, der dem Wert des folgenden Ausdrucks EQUAL ist:

(list 'pathname-name 'path) 

In Ihrem Fall, Sie nur wollen eine Funktion:

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

BTW, wenn Sie die CLHS überprüfen, sehen Sie, dass das erste Argument von defpackage kein Symbol zu sein braucht, aber jeder string designator.

+0

Vielen Dank, ich hatte das Gefühl, dass das Lernen von Common Lisp eine Menge darüber ist, wann und wann keine Makros zu verwenden sind. – dnolen

+0

Was Sie dort tun, ist ein Paket namens "(STRING-UPCASE NAME)" zu definieren - zumindest würden Sie das tun, wenn eine Liste ein gültiger String-Bezeichner wäre. In jedem Fall funktioniert Ihr Code nicht portabel. –

+0

Ein paar Probleme: a) def * normalerweise Namen Makros und b) sehen Matthias Antwort, wo er MAKE-PACKAGE erwähnt. (Ihre Funktion funktioniert nicht, weil DEFPACKAGE das erste Argument nicht auswertet. –