2013-07-02 10 views
7

W kontekście pisania makr Racket, co oznacza "składnia 3D"?Co to jest "składnia 3D"?

Słyszałem to zdanie kilka razy. W tym raz w odniesieniu do makro I było pisanie. Ale to było chwilę temu; Naprawiłem to i teraz nie pamiętam dokładnie, co robiłem źle.

Również: Czy składnia 3D zawsze jest błędna? Lub jest to jak eval (gdzie, jeśli uważasz, że musisz go użyć, prawdopodobnie jesteś w błędzie, ale są niektóre ważne zastosowania w rękach ekspertów)?

+0

W przyszłości może wszystko będzie dobrze udokumentowane! +1 dla trudności. Wygląda mi na dobre pytanie o nagrodę. Jedyne, co mogłem trafnie zlokalizować, to ta dyskusja: http://lists.racket-lang.org/dev/archive/2013-January/011637.html – jdero

Odpowiedz

6

Obiekty składniowe mają zwykle być tylko serializable data. Składnia 3D osłabia ten stan: pozwala nam przemycić dowolne wartości, a nie tylko zwykłe dane. To czyni je "3d": są wartościami, które wznoszą się ponad zwykłe płaskie obiekty, których można się spodziewać po obiektach składniowych.

Na przykład możemy zakraść wartości lambda!

#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))) 

Rozwiązanie to jest zwykle złe, ponieważ obecność takich wartości prawdopodobnie oznacza nieuzasadniona próba wycieku informacji po drugiej fazy kompilacji. Rezultat jest taki, że prawdopodobnie nie można go osobno skompilować. Jeśli widzisz błąd, który brzmi mniej więcej tak:

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

to jest to najprawdopodobniej spowodowane makro wyprodukował kawałek 3D składni, które nie mogą być serializowane do kodu bajtowego.

Czasami, w rzadkich sytuacjach, naprawdę potrzebujemy składni 3d, często w kontekście dynamicznej oceny. Jako konkretny przykład, debugger w DrRacket może chcieć zanotować składnię programu, aby aplikacje funkcjonalne bezpośrednio wywoływały funkcje debuggera, dzięki czemu możemy robić takie rzeczy, jak kolorowanie pokrycia kodu w edytorze programów. W tym sensie składnia 3d może działać jako kanał komunikacji między dynamicznie wycenianym kodem a jego otoczeniem.

+0

nawet w takich kontekstach wydaje się być czystsza, aby wstrzyknąć funkcję jako zależność na poziomie modułów. Chociaż, um, stepper jest pełen składni 3d. –

+0

Uzgodnione. Ale natknąłem się na kilka dziwnych problemów, próbując to zrobić: http://lists.racket-lang.org/dev/archive/2013-April/012126.html, i niestety nie mam czasu, aby dowiedzieć się, co dokładnie tego mi brakuje. – dyoo

+1

Po pierwsze, dziękuję za odpowiedź! Ponownie czytałem, zastanawiałem się i próbowałem uzyskać odpowiedź na twoją odpowiedź. Po pierwsze, uznałem, że odpowiedź wymagałaby mówienia o transformatorach składniowych, ale używasz eval i przestrzeni nazw i próbuję przemyśleć, co to oznacza. Ponadto jestem zdezorientowany i/lub rozproszony przez użycie przestrzeni nazw w twoim przykładzie i próbuję zrozumieć, czy to jest niezbędne, a jeśli tak, to jak/dlaczego. [To] (https://gist.github.com/greghendershott/5923364) jest prostsze. Daje taką samą odpowiedź: 10. Czy jest to odpowiednik, czy nie? –