KATEDR� INFORMATIKY� PÍRODOV…DECK� FAKULT� UNIVERZIT� PALACKÉHO� OLOMOU�

PARADIGMAT� PROGRAMOVÁN� 2� MAKR� �

Slajd� vytvo°il� Vilé� Vychodi� � Ja� Kone£n�

(KI� U� Olomouc� P� 2A� Lekc� � Makr� � � � 3�

Opakování (kvazikvotování) '(1 2 3 4 5) Z=) (1 2 3 4 5) '(1 (+ 2 3) 4 5) Z=) (1 (+ 2 3) 4 5) '(1 ,(+ 2 3) 4 5) Z=) (1 5 4 5) '(1 1)) 4 5) Z=) (1 2) 4 5) (define s '(a b c)) '(1 ,s 2) Z=) (1 (a b c) 2) '(1 ,@s 2) Z=) (1 a b c 2) '(1 '2 3) Z=) (1 (quote 2) 3) (1 2 3) Z=) (quote (1 2 3)) (1 2 3) Z=) (quasiquote (1 2 3)) '(1 '(2 3)) Z=) (1 (quasiquote (2 3))) '(1 '(,(+ 1 2) 3)) Z=) (1 (quasiquote 3) 3))) '(1 ,'(,(+ 1 2) 3)) Z=) (1 (3 3)) (KI, UP Olomouc) PP 2A, Lekce 3 Makra I 2 / 35 Problém: chceme upravit if tak, aby p°i absenci alternativního výrazu vracel #f nyní máme: (if (= 1 2) 'blah) Z=) nedenovaná hodnota chceme: (new-if (= 1 2) 'blah) Z=) #f nabízí se vy°e²it pomocí nové procedury: (define new-if (lambda (elem1 elem2) (if elem1 elem2 #f))) p°i volání new-if je vºdy vyhodnocen i druhý argument: (new-if #f blah-blah) Z=) Error (KI, UP Olomouc) PP 2A, Lekce 3 Makra I 3 / 35 Pot°ebujeme� b¥he� vyhodnocován� kaºd� výra� tvar�

(new-i� expr� expr2�

nahradi� výrazem�

(i� expr� expr� #f�

be� toh� ani� b� s� vyhodnocoval� expr� � expr�

Jiným� slovy�

pot°ebujem� zavés� p°edpis� kter� bud� provád¥� transformac� kódu� transformac� � � � konkrétn� £ás� kód� j� nahrazen� jino� p� transformac� prob¥hn� vyhodnocen� transformovanéh� kód� (defin� � 11� (new-i� (even� x� (� � 1)�

� transformac�

(i� (even� x� (� � 1� #f�

� vyhodnocen�

#�

(KI� U� Olomouc� P� 2A� Lekc� � Makr� � � � 3�

Jak se dívat na transformaci? m·ºeme si ji p°edstavit jako (klasickou) proceduru, které jsou p°edány argumenty v nevyhodnocené podob¥ transformace se v n¥kterých jazycích nazývá makroexpanze ;; transforma£ní procedura pro new-if (define new-if-trans (lambda (test expr . alt) (list 'if test expr (if (null? alt) #f (car alt))))) (new-if-trans 'e1 'e2 'e3) Z=) (if e1 e2 e3) (new-if-trans 'e1 'e2) Z=) (if e1 e2 #f) (new-if-trans '(even? x) '(+ x 1)) Z=) (if (even? x) (+ x 1) #f) (KI, UP Olomouc) PP 2A, Lekce 3 Makra I 5 / 35 krat²í °e²ení pomocí kvazikvotování (define new-if-trans (lambda (test expr . alt) '(if ,test ,expr (begin #f ,@alt)))) p°íklady transformace: (new-if-trans 'expr1 'expr2 'expr3) Z=) (if expr1 expr2 (begin #f expr3)) (new-if-trans 'expr1 'expr2) Z=) (if expr1 expr2 (begin #f)) (new-if-trans '(even? x) '(+ x 1)) Z=) (if (even? x) (+ x 1) (begin #f)) (KI, UP Olomouc) PP 2A, Lekce 3 Makra I 6 / 35 nouzov� °e²en� new-if� kter� s� ji� chov� ja� m� manuáln� spu²t¥n� transforma£n� procedur� následn� vyhodnocen� transformovanéh� výraz�

(eva� (new-if-tran� '(even� x� '(� � 1))�

Výhod� °e²ení�

poku� j� prvn� výra� nepravdivý� alternativn� výra� nen� vyhodnoce� tout� konstrukc� (new-if� lz� zastavi� rekurz� Nevýhod� °e²ení�

v²echn� p°edávan� argument� musím� explicitn� kvotova� transformovan� výra� musím� ru£n� vyhodnoti� pomoc� eva� eva� v� v¥t²in� interpret� pracuj� je� � globální� prost°ed� volán� j� nep°ehledn� (KI� U� Olomouc� P� 2A� Lekc� � Makr� � � � 3�

problém s lexikálními vazbami (let 4) (eval (new-if-transformer '(even? x) '(+ x 1)))) Z=) error: x not bound £áste£né °e²ení: pouºití (the-environment) ve v¥t²in¥ interpret· nebude fungovat (let 5) (eval (new-if-transformer '(even? y) '(+ y 1)) (the-environment))) navíc jsme se nezbavili nep°ehledného kódu e²ení problému: zavedení maker (KI, UP Olomouc) PP 2A, Lekce 3 Makra I 8 / 35 MAKR� � dv� základn� pohled� n� makr� 1� POHLED� Makr� jso� roz²í°ení� syntax� jazyka� makr� � dán� denic� svéh� transforma£níh� p°edpis�

p� na£ten� výraz� (READ� j� � n¥� proveden� makroexpanz� tut� fáz� provád� tzv� preproceso� a� p� dokon£en� expanz� v²ec� make� nastáv� vyhodnocován� výraz� nem� smys� uvaºova� poje� aplikac� makra� takt� n� makr� pohlíº� v¥t²in� PJ� C� DrScheme� Commo� LISP,� � � Výhod� p°ístupu� preproceso� � vlastn� eva� jso� zcel� nezávisl�

preproceso� m·º� bý� aktivová� okamºit� p� na£ten� výraz� umoº¬uj� snadno� kompilac� kód� (� kompilované� kód� ji� pochopiteln� ºádn� makr� nejsou� Nevýhod� p°ístupu� makr� jso� mim� jazyk� (£ast� s� zapisuj� odli²n¥� t°eb� � C�

makr� nejso� element� prvníh� °ád� (KI� U� Olomouc� P� 2A� Lekc� � Makr� � � � 3�

MAKR� � dv� základn� pohled� n� makr� 2� POHLED� Makr� jso� speciáln� element� jazyka� makr� � elemen� jazyk� obsahujíc� ukazate� n� transf� procedur�

transforma£n� procedur� � � � klasick� procedur� j� pot°eb� roz²í°i� eval� p°ípad� kd� s� prvn� prve� seznam� vyhodnot� n� makr� makr� jso� uºivatelsk� denovan� speciáln� formy� takt� n� makr� budem� pohlíºe� m� (dál� t°eb� PJ� M4� TEX� Výhod� p°ístupu� makr� jso� element� prvníh� °ád�

� makr� lz� pracova� jak� � daty� moho� dynamick� vznikat/zanika� z� b¥h� program� m·ºem� uvaºova� koncep� anonymníh� makra� Nevýhod� p°ístupu� � makroexpanz� docház� a� p°� £innost� eva�

praktick� znemoº¬uj� ú£inno� kompilac� kód� p°� neuváºené� pouºíván� make� komplikuj� lad¥n� program� (KI� U� Olomouc� P� 2A� Lekc� � Makr� � 1� � 3�

Motiva£n� p°íklad� denic� make�

(define-macr� new-i� (lambd� (<test� <expr� � <alt>� (lis� 'i� <test� <expr�

(i� (null� <alt>� #� (ca� <alt>))))�

;� new-if� pomoc� kvazikvotován�

(define-macr� new-i� (lambd� (<test� <expr� � <alt>�

'(i� ,<test� ,<expr� (begi� #� ,@<alt>)))�

(KI� U� Olomouc� P� 2A� Lekc� � Makr� � 1� � 3�

P°íkla� pouºit� makr�

;� new-if� pomoc� kvazikvotován�

(define-macr� new-i� (lambd� (<test� <expr� � <alt>�

'(i� ,<test� ,<expr� (begi� #� ,@<alt>)))�

(le� 6)

� aktivac� transforma£n� procedur� makr�

(i� (even� x� (� � 1� (begi� #f)�

� vyhodnocen� výraz� � prost°edí� kd� � m� vazb� 1�

1�

(KI� U� Olomouc� P� 2A� Lekc� � Makr� � 1� � 3�

Roz²í°ení EVAL Eval[E;P]: (A) Pokud je E cislo, . . . jako obvykle (B) Pokud je E symbol, . . . jako obvykle (C) Pokud je E seznam tvaru (E1 E2    En), pak nejprve provedeme vyhodnocení prvního prvku E1 v prost°edí P a výslednou hodnotu ozna£íme F1, to jest F1 := Eval[E1;P]. Mohou nastat £ty°i situace: (C.1) Pokud F1 je procedura, . . . jako obvykle (C.2) Pokud F1 je speciální forma, . . . jako obvykle (C.3) Pokud F1 je makro jehoº transforma£ní procedura je T, pak 1 F0 := Apply[T ; E2; : : : ; En] (F0 je výsledkem aplikace transf. procedury na nevyhodnocené arg.) 2 Výsledek vyhodnocení F elementu E v prost°edí P je denován F := Eval[F0 ;P] (F je výsledek vyhodnocení elementu F0 v prost°edí P). (C.e) Pokud F1 není procedura, speciální forma, ani makro, pak vyhodnocení kon£í chybou CHYBA: První prvek seznamu . . .  . (KI, UP Olomouc) PP 2A, Lekce 3 Makra I 13 / 35 Lad¥ní maker: základní princip potla£íme vyhodnocení transformovaného kódu vyuºívá dodate£né KVOTOVÁNÍ (define-macro new-if (lambda (test expr . alt) (list 'quote (list 'if test expr (if (null? alt) #f (car alt)))))) (new-if #f blah-blah) Z=) (if #f blah-blah #f) (define-macro new-if (lambda (test expr . alt) (if ,test ,expr (begin #f ,@alt)))) (new-if #f blah-blah) Z=) (if #f blah-blah (begin #f)) (KI, UP Olomouc) PP 2A, Lekce 3 Makra I 14 / 35 chceme vytvo°it and2 dvou argument· vracející #t nebo #f chceme vytvo°it pouze s pomocí if ;; nedosta£ující °e²ení pomocí procedury: (define and2 (lambda (elem1 elem2) (if elem1 (if elem2 #t #f) #f))) p°edchozí má váºný nedostatek: (and2 #f blah-blah) Z=) error (chceme #f) (KI, UP Olomouc) PP 2A, Lekce 3 Makra I 15 / 35 and� s� dv¥m� argument� vracejíc� konjunkc� pot°ebujeme� b¥he� vyhodnocován� kaºd� výra� (and� expr� expr2� nahradi� výraze� (i� expr� (i� expr� #� #f� #f� be� toh� ani� b� s� vyhodnocoval� expr� � expr� e²en� pomoc� makra� (define-macr� and� (lambd� (expr� expr2� '(i� ,expr� (i� ,expr� #� #f� #f))� (KI� U� Olomouc� P� 2A� Lekc� � Makr� � 1� � 3� Ukázky pouºití and2 (and2 1 (+ 1 2)) + (if 1 (if (+ 1 2) #t #f) #f) + #t (and2 #f blah-blah) + (if #f (if blah-blah #t #f) #f) + #f (and2 #t #f) + (if #t (if #f #t #f) #f) Z=) #f (KI, UP Olomouc) PP 2A, Lekce 3 Makra I 17 / 35 Anaforický if: if* if*, který pracuje stejn¥ jako if, ale umoº¬uje v druhém a t°etím výrazu pouºívat symbol $result, který bude vºdy navázaný na výsledek vyhodnocení prvního výrazu praktické roz²í°ení, místo: (if (member 'b '(a b c d)) (list 'nalezen (member 'b '(a b c d))) 'blah) sta£í napsat: (if* (member 'b '(a b c d)) (list 'nalezen $result) 'blah) Z=) (nalezen (b c d)) (KI, UP Olomouc) PP 2A, Lekce 3 Makra I 18 / 35 e²ení� b¥he� vyhodnocován� kaºd� výra� (if� expr� expr� expr3� pot°ebujem� nahradi� výrazem� (le� 7))� (KI� U� Olomouc� P� 2A� Lekc� � Makr� � 1� � 3� Ukázk� pouºit� if� be� $resul� s� chov� jak� normáln� i� (if� � � 3� � (le� 8)))� (i� $resul� (lis� (quot� nalezen� $result� (quot� blah))� � (naleze� (� � d)� V²imn¥t� si� � expandované� výraz� nejso� ºádn�

(KI� U� Olomouc� P� 2A� Lekc� � Makr� � 2� � 3�

i� pomoc� con� (define-macr� i�

(lambd� (tes� exp� alt�

'(con� (,tes� ,expr�

(els� ,alt)))�

i� pomoc� con� (be� nutnost� mí� alternativn� v¥tev�

(define-macr� i� (lambd� (tes� exp� � alt� '(con� (,tes� ,expr� (els� (begi� #� ,@alt))))�

podobn� jak� p°edchozí� al� vracím� nedenovano� hodnot�

(define-macr� i� (lambd� (tes� exp� � alt� '(con� (,tes� ,expr� (els� (begi� (cond� ,@alt))))�

(KI� U� Olomouc� P� 2A� Lekc� � Makr� � 2� � 3�

con� pomoc� i� musím� p°epsa� jede� cond-výra� pomoc� n¥kolik� if�

;� základn� con� pomoc� i� (pomoc� rekurzivníh� vno°ení�

(define-macr� con�

(lambd� clis�

(le� dive-if� 9))))))�

(KI� U� Olomouc� P� 2A� Lekc� � Makr� � 2� � 3�

P°íkla� pouºit�

(con� 10)� �

(i� (� � 3� (quot� blah� (i� (� � 10� (� � x� (i� (prop� � y� (lis� � y� (� 20)))� � �

(KI� U� Olomouc� P� 2A� Lekc� � Makr� � 2� � 3�

con� pomoc� i� musím� p°epsa� jede� cond-výra� pomoc� n¥kolik� if�

;� základn� con� pomoc� i� (°e²en� jak� rekurzivn� makro�

(define-macr� con�

(lambd� clis�

(i� (null� clist�

'(i� #� #f�

(i� (equal� (caa� clist� 'else�

(cada� clist�

'(i� ,(caa� clist�

,(cada� clist�

(con� ,@(cd� clist))))))�

(KI� U� Olomouc� P� 2A� Lekc� � Makr� � 2� � 3�

P°íkla� pouºit�

(con� 11)

(i� (� � 3� (quot� blah� (con� 12))�

� �

(KI� U� Olomouc� P� 2A� Lekc� � Makr� � 2� � 3�

Roz²í°en� verz� defin� defin� jsm� zatí� pouºíval� pouz� v� tvar�

(defin� symbo� /vyra� .�

� R6R� Schem� j� defin� zavede� tak� v� tvar�

(defin� (symbo� /argument� ….� /vyraz� ….�

P°íklad� faktoriá�

(defin� (� n�

(i� (� � 1�

(� � (� (� � 1))))�

P°íklad� nepovinn� argument�

(defin� (� � � � args� (lis� � � args)�

(KI� U� Olomouc� P� 2A� Lekc� � Makr� � 2� � 3�

Roz²í°ená verze define Pokud by ná² interpret nedisponoval roz²í°eným define, pak bychom jej mohli vyrobit jako makro: (define-macro def (lambda (first . args) (if (symbol? first) '(define ,first ,@args) '(define ,(car first) (lambda ,(cdr first) ,@args))))) P°íklad pouºití: (def (f n) (if (= n 1) 1 (* n (f (- n 1))))) (f 6) Z=) 720 (KI, UP Olomouc) PP 2A, Lekce 3 Makra I 28 / 35 Konjunkce libovoln¥ mnoha argument· pomocí if ;; základní verze (define-macro and (lambda args (if (null? args) #t '(if ,(car args) (and ,@(cdr args)) #f)))) (and 1 2 3) Z=) #t protoºe: (and 1 2 3) Z=) (if 1 (and 2 3) #f) Z=)    (and 2 3) Z=) (if 2 (and 3) #f) Z=)    (and 3) Z=) (if 3 (and) #f) Z=)    (and) Z=) #t Z=) #t (KI, UP Olomouc) PP 2A, Lekce 3 Makra I 29 / 35 Konjunkce libovoln¥ mnoha argument· pomocí if ;; zlep²ená verze (zobecn¥né pravdivostní hodnoty) (define-macro and (lambda args (if (null? args) #t (if (null? (cdr args)) (car args) '(if ,(car args) (and ,@(cdr args)) #f))))) nyní se jiº chová jako klasický and: (and) Z=) #t (and 1 2 3) Z=) 3 (and 1 #f 3) Z=) #f (KI, UP Olomouc) PP 2A, Lekce 3 Makra I 30 / 35 Disjunkce libovoln¥ mnoha argument· pomocí if ;; základní verze (define-macro or (lambda args (if (null? args) #f '(if ,(car args) #t (or ,@(cdr args)))))) P°íklad pouºití: (or) Z=) #f (or 1 2 3) Z=) #t cht¥li bychom 1 (or #f 2 3) Z=) #t cht¥li bychom 2 (KI, UP Olomouc) PP 2A, Lekce 3 Makra I 31 / 35 Disjunkce libovoln¥ mnoha argument· pomocí if ;; roz²í°ená verze (define-macro or (lambda args (if (null? args) #f (if (null? (cdr args)) (car args) '(if ,(car args) ,(car args) (or ,@(cdr args))))))) Chová se (zdánliv¥) v po°ádku: (or) Z=) #f (or 1 2 3) Z=) 1 (or #f 2 3) Z=) 2 (KI, UP Olomouc) PP 2A, Lekce 3 Makra I 32 / 35 Problémy s implementací disjunkce pomocí if na²e implementace or: dvakrát vyhodnocuje pravdivé argumenty (krom¥ posledního) d·sledek: nechová se jako klasický or pokud pouºijeme vedlej²í efekt Chování klasického or (let 13) (or (begin (set! x (+ x 1)) x) blah)) Z=) 1 Chování na²eho or: (let 14) (or (begin (set! x (+ x 1)) x) blah)) Z=) 2 (KI, UP Olomouc) PP 2A, Lekce 3 Makra I 33 / 35 Problémy s implementací disjunkce pomocí if ;; pokus o °e²ení p°edchozího problému (define-macro or (lambda args (if (null? args) #f (if (null? (cdr args)) (car args) '(let 15)) (if result result (or ,@(cdr args)))))))) Nyní uº jsme p°edchozí problém odstranili, . . . (let 16) (or (begin (set! x (+ x 1)) x) blah)) Z=) 1 (KI, UP Olomouc) PP 2A, Lekce 3 Makra I 34 / 35 . . . ale nový problém jsme vyrobili Klasický or: (let 17) (or #f result)) Z=) 10 Ná² or: (let 18) (or #f result)) + (let 19) (if result result (or result))) Z=) #f do²lo k p°ekrytí symbolu result symbolem stejného jména, který je pouºíván uvnit° na²eho makra tomuto efektu se °íká symbol capture (variable capture) v dal²í lekci ukáºeme £isté °e²ení tohoto problému (KI, UP Olomouc) PP 2A, Lekce 3 Makra I 35 / 35

1)
,(+ 2 3
2)
5
3)
unquote (+ 1 2
4)
x 10
5)
y 10
6)
� 10)� (new-i� (even� x� (� � 1
7)
$resul� expr1)� (i� $resul� expr� expr3)� � t� op¥� be� vyhodnocován� expr� a� expr� if� jak� makr� (define-macr� if� (lambd� (tes� exp� � alt� '(le� (($resul� ,test)� (i� $resul� ,exp� ,@alt
8)
$resul� 1)� (i� $resul� � 3)� � � p°íkla� pouºit� $resul� (if� � $resul� 3� � (le� (($resul� 1)� (i� $resul� $resul� 3)� � � (KI� U� Olomouc� P� 2A� Lekc� � Makr� � 2� � 3� Sloºit¥j²� ukázk� pouºit� if� (if� (membe� '� '(� � � d)� (lis� 'naleze� $result� 'blah� � (le� (($resul� (membe� (quot� b� (quot� (� � � d
9)
clis� clist)� (i� (null� clist� '(i� #� #f� (i� (equal� (caa� clist� 'else� (cada� clist� '(i� ,(caa� clist� ,(cada� clist� ,(dive-if� (cd� clist
10) , 11)
� � 3� 'blah� ((� � 10� (� � x)� ((prop� � y� (lis� � y)� (els� (� 20
12)
� � 10� (� � x)� ((prop� � y� (lis� � y)� (els� (� 20
13) , 14) , 16)
x 0
15)
result ,(car args
17) , 18)
result 10
19)
result #f
PAPR2/pp2a3.txt · Last modified: 2014/04/24 00:53 (external edit)
CC Attribution-Noncommercial-Share Alike 4.0 International
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0