2013-07-02 11 views
7

Was bedeutet "3D-Syntax" im Zusammenhang mit dem Schreiben von Racket-Makros?Was ist "3D-Syntax"?

Ich habe den Satz ein paar Mal gehört. Einschließlich in Bezug auf ein Makro I wurde geschrieben. Aber das war eine Weile her; Ich habe es behoben, und jetzt kann ich mich nicht mehr genau erinnern, was ich ursprünglich falsch gemacht habe.

Auch: Ist 3D-Syntax immer schlecht? Oder ist es wie eval (wo, wenn Sie denken, dass Sie es verwenden müssen, sind Sie wahrscheinlich falsch, aber es gibt einige gültige Verwendungen in erfahrenen Händen)?

+0

In Zukunft wird vielleicht alles gut dokumentiert sein! +1 für die Schwierigkeit. Sieht für mich nach einer guten Kopfgeldfrage aus. Das einzige, was ich relevant finden konnte, war diese Diskussion: http://lists.racket-lang.org/dev/archive/2013-Januar/011637.html – jdero

Antwort

6

Syntaxobjekte sollen normalerweise nur serializable data sein. Die 3D-Syntax schwächt diese Bedingung: Sie ermöglicht es uns, beliebige Werte einzuschleusen und nicht nur reine Daten. Das macht sie zu "3d": Sie sind Werte, die über die normalen flachen Dinge hinausgehen, die man von Syntaxobjekten erwarten würde.

Zum Beispiel können wir in lambda Werte schleichen!

#lang racket 

(define ns (make-base-namespace)) 
(define (set-next! n) 
    (parameterize ([current-namespace ns]) 
    (eval #`(define next #,n)))) ;; <-- 3d-syntax here 

(define (compute s) 
    (parameterize ([current-namespace ns]) 
    (eval s))) 

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
(define counter 0) 
(set-next! (lambda() 
      (set! counter (add1 counter)) 
      counter)) 

(compute '(+ (next) 
      (next) 
      (next) 
      (next))) 

tut dies in der Regel eine schlechte Sache, weil das Vorhandensein solchen Wertes bedeutet wahrscheinlich einen unbegründeten Versuch, Informationen über Phasen der Kompilierung zu lecken. Das Ergebnis ist wahrscheinlich nicht separat kompilierbar. Wenn Sie einen Fehler sehen, die wie etwas klingt:

write: cannot marshal value that is embedded in compiled code value 

dann ist das höchstwahrscheinlich auf ein Makro ein Stück 3D-Syntax erzeugt zu haben, die nicht zu Bytecode serialisiert werden kann.

Manchmal, in seltenen Situationen, wollen wir wirklich 3D-Syntax, oft in dynamischen Bewertungskontexten. Als ein konkretes Beispiel möchte ein Debugger in DrRacket vielleicht die Syntax eines Programms annotieren, so dass Funktionsanwendungen direkt in Funktionen des Debuggers zurückrufen, so dass wir Dinge wie eine interaktive Codeüberdeckungseinfärbung im Programmeditor tun können. In diesem Sinne kann die 3d-Syntax als Kommunikationskanal zwischen dynamisch evaluiertem Code und seiner Umgebung dienen.

+0

selbst in Kontexten wie diesem scheint es jedoch sauberer zu sein, die Funktion zu injizieren als eine Abhängigkeit auf Modulebene, irgendwie. Obwohl, ähm, ist der Stepper voller 3D-Syntax. –

+0

Einverstanden. Aber ich stieß auf einige seltsame Probleme mit dem Versuch, dies zu tun: http://lists.racket-lang.org/dev/archive/2013-April/012126.html, und leider habe ich in diesen Tagen keine Zeit, um herauszufinden, was genau ich vermisse. – dyoo

+1

Zuerst, danke für die Antwort! Ich habe wieder gelesen, nachgedacht und versucht, deine Antwort in den Griff zu bekommen. Zum einen dachte ich, die Antwort würde bedeuten, über Syntaxtransformatoren zu sprechen, aber Sie verwenden Eval und Namespaces, und ich versuche darüber nachzudenken, was das bedeutet. Außerdem bin ich verwirrt und/oder abgelenkt durch die Verwendung von Namespaces in Ihrem Beispiel und versuche zu verstehen, ob das wichtig ist und wenn ja, wie/warum. [This] (https://gist.github.com/greghendershott/5923364) ist einfacher. Es gibt die gleiche Antwort: 10. Ist es gleichwertig oder nicht? –