2014-10-27 30 views
6

In Common Lisp ist es relativ einfach, ein makrodefinierendes Makro zu erstellen. Beispiel: Das folgende MakroMakrodefinierendes Makro im Racket?

(defmacro abbrev (short long) 
    `(defmacro ,short (&rest args) 
    `(,',long ,@args))) 

ist ein makrodefinierendes Makro, da es auf ein anderes Makro erweitert wird.

Wenn wir jetzt

(abbrev def defun) 

in unserem Programm setzen, können wir def statt defun schreiben, wenn wir eine neue Funktion definieren. Natürlich kann abbrev auch für andere Dinge verwendet werden. Zum Beispiel, nach

(abbrev /. lambda) 

können wir (/. (x) (+ x 1)) statt (lambda (x) (+ x 1)) schreiben. Nett. (Ausführliche Erläuterung der Abk finden http://dunsmor.com/lisp/onlisp/onlisp_20.html)

Nun meine Fragen sind:

  1. Kann ich die Makro definieren Makros in Racket schreiben?
  2. Wenn ich kann, wie geht das? (Zum Beispiel, wie etwas ähnliches wie abbrev Makro in Racket schreiben?)
+0

Sie invertiert Ihre Makro-Parameter, lange sollte zuerst kommen. – uselpa

+0

Ich habe das in meiner Frage korrigiert. Panzer! –

Antwort

8

Nach this Teil des Schläger Guide:

(define-syntax-rule (abbrev short long) 
    (define-syntax-rule (short body (... ...)) 
    (long body (... ...)))) 

den Link oben Zitiert:

Der einzige nicht offensichtliche Teil seiner Definition ist die (... ...), die "Anführungszeichen" ... so dass es seine übliche Rolle im generierten Makro anstelle des generierenden Makros übernimmt.

Jetzt

(abbrev def define) 
(abbrev /. lambda) 
(def f (/. (x) (+ x 1))) 
(f 3) 

ergibt

4 

FWIW, sich auf Guile funktioniert auch, so dass es keine Racket-spezifische Sache.

5

ad 1. Ja. ad 2. Ihr Beispiel kann am einfachsten geschrieben werden

#lang racket 

(define-syntax (abbrev stx) 
    (syntax-case stx() 
    [(_ short long) 
    #'(define-syntax short (make-rename-transformer #'long))])) 

(abbrev def define) 
(def x 42) 
x 

Das obige Beispiel wertet bis 42

+0

Der Begriff "neu" schafft hier Verwirrung ("kurz" ist eigentlich ein neuer Begriff). Es wird klarer, wenn "lang" (statt "neu") verwendet wird, wie an anderen Stellen auf dieser Seite. – rnso

+0

stimme ich zu. Ich habe es geändert. – soegaard

0

Ich finde, dass die Umbenennung einfach mit definieren oder lassen Aussagen gemacht werden können:

(define =? =) 
(define lr list-ref) 

oder:

(let ((=? =) 
     (lr list-ref)) 
    (println (lr '(1 2 3) 2)) 
    (println (=? 1 2)) 
    (println (=? 1 1))) 

Ausgang:

3 
#f 
#t 

Es scheint nicht notwendig zu sein, irgendein Makro für diesen Zweck.

+0

Das funktioniert nicht, wenn Sie ein spezielles Formular oder ein Makro wie 'define' oder' lambda' umbenennen wollen. –

+0

Was dann funktioniert, ist '(define-syntax def (make-rename-transformer # 'definieren))' oder ' (definiere-syntax /. (make-rename-transformer # 'lambda)) ' –