Schon ein wenig her, aber ich versuche mich mal dran:
(for-each (i (list 1 2 3)) (write i) (terpri))
ist meine Eingabe, die das Macro übersetzen soll - das terpri dient nur dem Zeilenvorschub nach der Ausgabe. Ich habe mich mal dazu entschlossen, keine vorhandenen Schleifen-Befehle zu verwenden, sondern mit Rekursion zu arbeiten.
Das heißt, aus dem obigen soll etwas werden, das in etwa so aussieht:
(labels ((func-name (l)
(when l
(let ((i (car l)))
(write i)
(terpri))
(func-name (cdr l)))))
(func-name lst))
Da wird also die Funktion func-name mit der Liste aufgerufen. Solange die Liste nicht leer ist, wird das erste Element der Liste der Variablen i zugewiesen und die Befehle abgearbeitet. Anschließend ruft sich die Funktion rekursiv mit dem Rest der Liste (ohne das erste Element) auf, bis die Liste leer ist.
Ein Macro, dass dies bewerkstelligt könnte beispielsweise so aussehen:
(defmacro for-each(box &rest body)
(destructuring-bind (var lst) box
(let ((func-name (gensym)))
`(labels ((,func-name (l)
(when l
(let ((,var (car l)))
,@body)
(,func-name (cdr l)))))
(,func-name ,lst)))))
Wendet man den Befehl macroexpand auf dieses Beispiel an, dann erhält man:
(macroexpand '(for-each (i (list 1 2 3)) (write i) (terpri)))
(LABELS ((#:G557 (L)
(WHEN L
(LET ((I (CAR L)))
(WRITE I)
(TERPRI))
(#:G557 (CDR L)))))
(#:G557 (LIST 1 2 3)))
Schön zu sehen ist hier, wie der Name der Funktion durch das gensym automatisch gewählt wird.
Was du allerdings mit dem translate meinst, habe ich nicht ganz begriffen. Vielleicht kannst du das nochmal genauer erläutern?
Vlati