2013-07-02 10 views
18

Czytam Let Over Lambda, która zajmuje się bardzo głęboko warstwowym tworzeniem makr. To fascynujące i zazwyczaj staram się nadążyć za tym.Powszechne podwójne cytaty z Lisp-a, niekrytyczne, cytatowe, niekryte sekwencje?

W rozdziale 4 Hoyte realizuje makr czytnik meczu CL-PPCRE i zastąpić funkcje, takie, że można robić takie rzeczy jak:

(#~m/(foo|bar)\d+/ "Some foo99") ; matches! 
(#~s/foo(\d+)/bar\1/, "Some foo99") ; "Some bar99 

Aby osiągnąć ten cel, możemy zdefiniować makro, które używa dwukrotnie backquote, ponieważ jest on faktycznie rozszerzany przez makro opakowania, które potrzebuje wartości cytowanej (zwraca formularz lambda). W obrębie quasi-cytowanej listy, istnieje pewne użycie następującej sekwencji ,',varname, której nie mogę się obrócić. Co robi tutaj początkowa ,'?

(defmacro! pcre/match-lambda-form (o!args) 
    "Expands to a lambda that applies CL-PPCRE:SCAN" 
    ``(lambda (,',g!str) 
     (cl-ppcre:scan ,(car ,g!args) 
        ,',g!str))) 

Właściwie, to chyba lepiej, że destylować, że do czegoś, która używa tylko defmacro, dla jasności, jeśli nie czytać książki. str jest symbolem i args jest lista:

(defmacro pcre/match-lambda-form (args) 
    "Expands to a lambda that applies CL-PPCRE:SCAN" 
    ``(lambda (,',str) 
     (cl-ppcre:scan ,(car ,args) 
        ,',str))) 

Czy cytaty zasadzie podwójnego cytowania części wewnętrznych, tak, że wynik może być cytowane dwa razy? Skutecznie wstawiając 'str do rozwiniętej formy, zamiast tylko str?

EDYCJA | Dzięki Terje D. i jakiejś zabawy w REPL, to jest dość dużo sytuacja:

(defvar a 42) 

(equal ``(,,a) '(list 42)) ; T 
(equal ``(,a) '(list a)) ; T 
(equal ``(,',a) ''(42))  ; T 
(equal ``(a) ''(a))  ; T (obviously) 

Więc:

  • podwójnie cytowane, forma jest w pełni rozwinięty.
  • Formularz pojedynczy, niecytowany, nie jest rozszerzany.
  • Bez cudzysłowu z przecinkiem, formularz jest w pełni rozwinięty i cytowany wynik.
+0

Twoja ostatnia referencje defmacro 'str'. Co to jest? Gdzie to jest zdefiniowane? Czy możesz pokazać, jak nazywa się 'pcre/match-lambda-form'? –

+0

Argh, to wymaga wyjaśnienia, ponieważ w rzeczywistości dzieje się wiele warstw makr. Ta książka przesuwa granice z tworzeniem makr (dla zabawy i dla edukacji).'str' jest symbolem, który został zdefiniowany przez otaczający' LET' i reprezentuje nazwę zmiennej, która jest bezpieczna w użyciu. – d11wtq

+0

'pcre/match-lambda-form' jest nazywane tak:' (pcre/match-lambda-form '("foo")) ', gdzie' 'foo" 'zostało odczytane przez łańcuch przetwarzający strumienie formularz '# ~ m/foo /'. – d11wtq

Odpowiedz

11

Podczas oceny podwójnie odwróconej formy wewnętrzna kopia wewnętrzna jest traktowana jako pierwsza, a wynikiem jest pojedyncza forma z odwróceniem. Podczas oceny wewnętrznego formularza wstecznego oceniane są tylko elementy poprzedzone dwoma przecinkami. Jednak wynik oceny tych podwójnie niecałkowitych elementów jest nadal (pojedynczo) niecałkowity, a zatem są one ponownie oceniane, gdy oceniany jest wynikowy pojedynczy, jednokrotnie wsteczny formularz. Aby uzyskać ocenę tylko w wewnętrznym formularzu wstecznym, należy wstawić zwykłą wycenę, co daje ,',.

Zobacz jak

(let ((tmp (gensym))) 
    ``(lambda (,tmp ,,tmp ,',tmp)())) 

ocenia się

`(LAMBDA (,TMP ,#:G42 #:G42) nil) 
+1

Wow, to trochę skomplikowane. Po prostu bawię się z kilkoma podstawowymi podwójnymi zwrotami wstecznymi i tymi odmianami, które obecnie są nieaktualne, aby zobaczyć, co dzieje się w każdym przypadku. Rozumiem, dziękuję :) – d11wtq

+2

@ d11wtq Możesz również rzucić okiem na załącznik C (backquote) z "Common Lisp the Language" dostępny na http://www.cs.cmu.edu/Groups/AI/ html/cltl/clm/node1.html, który zawiera przykładową implementację i przykłady składni wstecznej. –

1

The ', X trik służy do osłaniania X z innej oceny.

Zobacz jak:

 (setq a 'fn) 
    (let ((x 'a)) ``(,,x ,',x)) ==> `(,a a) ==> (fn a) 

    ;; ``,',X ==> `,(quote "the value of X") ==> "the value of X" 

    ;; ``,,X ==> `,"the value of X" ==> "the value of the value of X"