2008-10-29 8 views
9

Viele Beispiele von Makros scheinen über das Verstecken von Lambdas zu sein, z.B. mit-öffnen-Datei in CL. Ich suche nach etwas exotischeren Anwendungen von Makros, insbesondere in PLT Scheme. Ich möchte ein Gefühl dafür bekommen, wann ich eine Makro-Funktion in Betracht ziehen sollte.Für welche Dinge haben Sie Scheme-Makros verwendet?

+1

PLT-Schema heißt jetzt Racket. Siehe http://www.racket-lang.org/ – Stephen

Antwort

5

Ich verwende nur Scheme-Makros (define-syntax) für kleine Dinge wie bessere Lambda-Syntax:

(define-syntax [: x] 
    (syntax-case x() 
    ([src-: e es ...] 
    (syntax-case (datum->syntax-object #'src-: '_)() 
     (_ #'(lambda (_) (e es ...))))))) 

Welche Sie

schreiben
[:/_ 2] ; <-- much better than (lambda (x) (/ x 2)) 

Dan Friedman hat eine knifflige Implementierung von OO-Makros können : http://www.cs.indiana.edu/~dfried/ooo.pdf

Aber ehrlich gesagt, alle nützliche Makros, die ich definiert habe d sind gestohlen von Paul Graham's On Lisp und sind in der Regel einfacher zu schreiben mit defmacro (define-macro in PLT Scheme). Zum Beispiel ist aif mit define-syntax ziemlich hässlich.

(define-syntax (aif x) 
    (syntax-case x() 
    [(src-aif test then else) 
    (syntax-case (datum->syntax-object (syntax src-aif) '_)() 
     [_ (syntax (let ([_ test]) (if (and _ (not (null? _))) then else)))])])) 

define-syntax ist in seltsam, dass es nur leicht, sehr einfachen Makros verwenden, wo man froh über die Unfähigkeit ist Variablen zu erfassen; und sehr komplizierte Makro-DSLs, wo Sie froh sind, dass die Variablen nicht leicht zu erfassen sind. Im ersten Fall wollen Sie den Code schreiben, ohne darüber nachzudenken, und im zweiten Fall haben Sie genug über die DSL gedacht, dass Sie bereit sind, einen Teil davon in die syntax-rules/syntax-case Sprache zu schreiben, die nicht Schema ist, um zu vermeiden mystifizierende Bugs.


Aber ich verwende Makros nicht so viel in Schema. Idiomatische Scheme ist so funktional, dass Sie oft nur ein funktionales Programm schreiben und dann ein paar Lambdas verstecken wollen. Ich bin in den Funktionszug eingestiegen und glaube jetzt, dass, wenn Sie eine faule Sprache oder eine gute Syntax für Lambda haben, auch das nicht notwendig ist, also sind Makros nicht so nützlich in einem rein funktionalen Stil.

So würde ich Practical Common Lisp und On Lisp empfehlen. Wenn Sie PLT-Schema verwenden möchten, denke ich, dass die meisten ihrer defmacro Makros mit define-macro arbeiten. Oder benutze einfach Common Lisp.

+1

Wenn Sie einen Syntax-Parameter verwenden, wird 'aif' viel sauberer zu definieren (und hygenisch!):' (Define-syntax-parameter it #f) (define-syntax aif (syntax-parser [(_ test then else) # '(let ([Ergebnistest]) (syntax-parametrisiere ([es (make-rename-transformer result)]) (wenn Ergebnis dann else)))])) – Jack

7

Ich fange an, die letzte Frage zu beantworten. Wann sollte ein Makro anstelle einer Funktion verwendet werden? Die Makros tun Dinge, die die Funktionen nicht können, und die Funktionen, die die Makros nicht ausführen können, also wird es schwierig sein, sie zu mischen, aber lasst uns tiefer gehen.

Sie verwenden Funktionen, wenn die Argumente ausgewertet werden sollen, und Makros, wenn die Argumente nicht ausgewertet werden sollen. Das ist nicht sehr nützlich, oder? Sie verwenden Makros, wenn Sie etwas anders schreiben möchten, wenn Sie ein Muster sehen und es abstrahieren möchten. Zum Beispiel: Ich definiere drei Funktionen namens foo-create, foo-process und foo-destroy für verschiedene Werte von foo und mit ähnlichen Körpern, wo die einzige Änderung foo ist. Es gibt ein Muster, aber eine zu hohe Ebene für eine Funktion. Sie erstellen also ein Makro.

In meiner bescheidenen Erfahrung, Makros in Scheme sind so viel wie in anderen Lisps, wie Common Lisp oder Clojure zu verwenden. Ich nehme an, es ist ein Beweis, dass hygienische Makros vielleicht keine so gute Idee sind, und hier würde ich Paul Graham nicht zustimmen, warum. Es liegt nicht daran, dass man manchmal schmutzig (unhygienisch) sein möchte, sondern weil hygienische Makros komplex oder gewunden sind.

+0

"weil Hygienemakros am Ende komplex oder verschachtelt sind" - ich glaube nicht, dass dies an der Hygiene an sich liegt; es ist wahrscheinlicher, weil Schema hygienische Makros "high-level" sind und in einer anderen Sprache als Schema geschrieben sein müssen (was für mich viel weniger praktisch ist als Schema selbst!) Deshalb liebe ich Common Lisp und benutze immer noch define-macro in Scheme, obwohl R5RS dieses awckward-syntax-rules-ding hat ...:-) – Jay

3

Praktische gemeinsame Lisp, von Peter Seibel, hat eine gute Einführung in Makros. Auf Lisp, von Paul Graham, könnte eine gute Quelle für kompliziertere Beispiele sein. Schauen Sie sich auch die eingebauten Makros an, zum Beispiel Common Lisp.

+1

Scheme-Makros = Gemeinsame Lisp-Makros –

1

Ein Beispiel für eine fortgeschrittenere Makro, das nicht eine Lambda-Form in der Verkleidung ist die Common Lisp Makro mit Schlitzen, die Zugriffsobjektschlitz wie gewöhnliche variable Zugang Look macht:

(with-slots (state door) car 
    (when (eq state :stopped) 
    (setq state :driving-around) 
    (setq door :closed))) 

Beachten Sie, dass diese ist nicht das Gleiche wie das Binden der Slot-Werte an lokale Variablen und den Zugriff auf diese, wie mit Slots können Sie Slots über SETQ ändern und externe Änderungen sofort sehen.

+0

Die Verwendung von setq ist wirklich zugunsten von setf veraltet. Es ist weniger verwirrend für neue (gemeinsame) Lispern, wenn Beispiele wie dies setf verwenden. – simon

8

Makros werden benötigt, um neue Kontrollstrukturen und neue Bindungskonstrukte zu implementieren.

Suchen Sie daher nach diesen Arten von Konstrukten unter http://planet.plt-scheme.org. Bei PLaneT durchsuchen Sie beide die Dokumentation und den Code.

Beispiele für neue Kontrollstrukturen:

http://planet.plt-scheme.org/package-source/soegaard/control.plt/2/0/planet-docs/manual/index.html

Um Beispiele für neue Bindungsformen, suchen Sie nach Makros zu finden, die mit „mit-“ beginnen. Ein nützliches Beispiel finden Sie in math.plt auch von PLaneT.

; Within a (with-modulus n form1 ...) the return values of 
    ; the arithmetival operations +, -, * and^are automatically 
    ; reduced modulo n. Furthermore (mod x)=(modulo x n) and 
    ; (inv x)=(inverse x n). 

    ; Example: (with-modulus 3 (^ 2 4)) ==> 1 

    (define-syntax (with-modulus stx) 
    (syntax-case stx() 
     [(with-modulus e form ...) 
     (with-syntax ([+ (datum->syntax-object (syntax with-modulus) '+)] 
        [- (datum->syntax-object (syntax with-modulus) '-)] 
        [* (datum->syntax-object (syntax with-modulus) '*)] 
        [^ (datum->syntax-object (syntax with-modulus) '^)] 
        [mod (datum->syntax-object (syntax with-modulus) 'mod)] 
        [inv (datum->syntax-object (syntax with-modulus) 'inv)]) 
     (syntax (let* ([n e] 
         [mod (lambda (x) (modulo x n))] 
         [inv (lambda (x) (inverse x n))] 
         [+  (compose mod +)] 
         [-  (compose mod -)] 
         [*  (compose mod *)] 
         [square (lambda (x) (* x x))] 
         [^  (rec^(lambda (a b) 
             (cond 
              [(= b 0) 1] 
              [(even? b) (square (^ a (/ b 2)))] 
              [else  (* a (^ a (sub1 b)))])))]) 
        form ...)))])) 
3

Das Automata via Macros Papier stellt eine funktionale Programmierung Perle auf Finite-State-Maschinen über Makros in Schema zu implementieren.

Das Buch The Reasoned Schemer endet mit einer vollständigen Makro-basierten Implementierung von miniKanren, der logischen Programmiersprache, die im Buch verwendet wird. This paper präsentiert miniKanren und seine Umsetzung formaler und prägnanter als im Buch.

+0

Das Automata via Macros-Link ist reines Gold. Ich hatte ein großes Aha! Moment es zu lesen. +1 von mir. –

0

Ich benutze sie, wenn die Verfahren nicht ausreichen.

1

Ich hatte einen curry Makro, als ich eine Menge Schema auf meiner Handfläche machte. Es war ziemlich praktisch.

1

Mit Scheme-Makros können Sie Funktionen hinzufügen, die die ursprünglichen Autoren nicht selbst enthalten. Das ist die ganze Philosophie hinter Macros.

Hier ist ein kleines Beispiel: PLT Scheme bietet eine Sprache zum Schreiben von Präsentationen, Slideshow genannt. Ich habe Makros verwendet, um einer Folie eine Foliennummer zuzuordnen, damit ich sie einfacher verwalten kann.

1

Ich habe ein Makro geschrieben, das Infix-Syntax bietet. Nichts zu ausgefallen; kein Vorrang. Während mir die Präfixsyntax generell gut geht, bevorzuge ich Infix für < und>.

Verwandte Themen