Frage

Viele Beispiele von Makros scheinen zu verstecken lambdas, zum Beispiel zu sein mit-open-Datei in CL. Ich suche für einige exotischere Anwendungen von Makros, vor allem in PLT Scheme. Ich mag ein Gefühl dafür bekommen, wenn im Vergleich mit den Funktionen mithilfe eines Makros zu berücksichtigen.

War es hilfreich?

Lösung

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 können Sie schreiben

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

Dan Friedman hat eine knifflige Implementierung von OO mit Hilfe von Makros: http: // www.cs.indiana.edu/~dfried/ooo.pdf

Aber ehrlich gesagt, alle nützlich Makros I definiert haben gestohlen von Paul Grahams On Lisp und ist in der Regel einfacher, mit defmacro (define-macro in PLT Scheme) zu schreiben. Zum Beispiel ist aif ziemlich hässlich mit define-syntax.

(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 seltsam, dass es nur leicht, sehr einfachen Makros verwenden, wo man froh über die Unfähigkeit ist Variablen zu erfassen; und sehr komplizierter Makro DSLs, wo man froh über die Unfähigkeit zu erfassen Variablen leicht . 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 der syntax-rules / syntax-case Sprache zu schreiben, die nicht Schema ist, um zu vermeiden, mystifying Fehler.


Aber ich benutze keine Makros, die viel in Schema. Idiomatisches Schema ist so funktional, dass viele Male Sie nur ein funktionsfähiges Programm schreiben wollen, und dann verstecken ein paar lambdas. Ich habe auf dem funktionalen Zuge und jetzt glaube, dass, wenn Sie einen faulen Sprache oder eine gute Syntax für Lambda, auch das ist nicht nötig, so Makros ist nicht alles, was nützlich in einem rein funktionalen Stil.

Also ich würde empfehlen, Practical Common Lisp und Auf Lisp . Wenn Sie PLT Scheme verwenden wollen, glaube ich, die meisten ihrer defmacro Makros mit define-macro arbeiten. Oder einfach nur Common Lisp verwenden.

Andere Tipps

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

So suchen diese Arten von Konstrukten unter http://planet.plt-scheme.org . Bei planen Sie beide sehen 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 zu finden, suchen Sie nach Makros, die mit „mit-“ beginnen. Ein nützliches Beispiel ist in math.plt findet auch aus plante.

  ; 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 ...)))]))

Ich beginne die letzte Frage zu beantworten. Wenn ein Makro anstelle einer Funktion zu verwenden. Die Makros Dinge tun, die Funktionen nicht können, und die Funktionen zu tun, was die Makros können nicht, so dass es dann schwierig sein, sie zu mischen, aber sie tiefer gehen.

Sie Funktionen verwenden, wenn Sie die Argumente wollen ausgewertet und Makros, wenn Sie die Argumente un-ausgewertet werden soll. Das ist nicht sehr nützlich, oder? Sie verwenden Makros, wenn Sie etwas in einer anderen Art und Weise schreiben möchten, wenn Sie ein Muster zu sehen, und Sie wollen abstrakt. Zum Beispiel: foo erstellen, foo-Prozess und foo-zerstören für verschiedene Werte von foo und mit ähnlichen Einrichtungen, wo die einzige Änderung foo genannt ist definiere ich drei Funktionen. Es gibt ein Muster, sondern ein zu hohes Niveau für eine Funktion, so dass Sie erstellen ein Makro.

In meiner bescheidenen Erfahrung, Makros in Scheme sind so viel wie in anderen Lisps, wie Common Lisp oder Clojure verwendet. Ich nehme an, es ist Beweis, dass vielleicht hygienische Makros sind nicht so eine gute Idee, und hier würde ich mit Paul Graham anderer Meinung darüber, warum. Es ist nicht, weil man manchmal sein schmutzig will (un-hygienisch), sondern weil hygienische Makros sind komplex oder verworren enden.

Practical Common Lisp, von Peter Seibel, hat eine gute Einführung in die Makros. Auf Lisp, von Paul Graham, könnte eine gute Quelle für kompliziertere Beispiele sein. Außerdem hat Blick auf den integrierten Makros in, sagen sie, Common Lisp.

Die Automata über Makros Papier stellt eine funktionale Programmierung pearl Finite-State-Maschinen über Makros in Schema bei der Umsetzung.

Das Buch Der mit Gründen versehene Schemer mit einem Ende vollständige Makro-basierte Implementierung von miniKanren, Sprache der Logikprogrammierung im Buch verwendet. Dieses Papier miniKanren und deren Umsetzung formeller und prägnant als im Buch präsentiert.

Ein Beispiel für eine fortgeschrittenere Makro, das nicht eine Lambda-Form in der Verkleidung ist, Makros Common Lisp mit Schlitzen , die den Zugang Objekt Schlitz aussehen wie normale Variable Zugriff macht:

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

Beachten Sie, dass dies nicht das gleiche ist, die Schlitzwerte auf lokale Variablen als verbindlich an und diejenigen Zugriff als mit Schlitzen können Sie Slots haft SETQ verändern und sofort externe Veränderungen sehen.

Ich hatte einen curry Makro, wenn ich viel Schema auf meiner Handfläche zu tun, verwendet. Es war ziemlich praktisch.

Scheme-Makros können Sie Funktionen hinzufügen, die die ursprüngliche Sprache Autoren nicht selbst enthielten; das ist die ganze Philosophie hinter Makros.

Hier ist ein kleines Beispiel: PLT Scheme bietet eine Sprache zum Schreiben von Präsentationen genannt Slideshow. Ich benutzte Makros eine Dianummer mit einem Schieber zu verbinden, so dass ich sie leichter verwalten können.

Ich habe ein Makro geschrieben, die Infix-Syntax zur Verfügung stellt. Nichts Besonderes; kein Vorrang. Während ich in der Regel gut mit Präfix Syntax bin, ziehe ich Infix für .

Ich benutze sie, wenn Verfahren nicht ausreichen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top