Nemůžete přece chtít, aby se v nějakém jazyce implementovaly obraty s něčím, co daný jazyk v takové podobě vůbec nemá.
a v tom bude asi jadro pudla. silne mi to tady zacina zavadet podobenstvi o jeskyni....
tak si zkusime nejaky prakticky priklad... co treba line vyhodnocovani, kod je ve schemu, ale to je jedno.
vytvorme si novy typ hodnot, tzv. prislib. do teto hodnoty si ,,schovame'' nejaky vyraz a vyhodnotime ho az kdyz bude opravdu potreba. nadefinujeme si teda macro:
(define-macro (delay x) `(lambda () x))
,
ktere zajisti, ze na miste v kodu kde se vyskytlo (delay foo), bude tento vyraz nahrazeny (lambda () foo), coz neni nic jineho nez anonymni funkce majici v sobe jako telo foo. jako foo, muze byt jakykoliv vyraz, ktery se pri deklaraci nevyhodnocuje! takze jde pouzit treba (delay (if (< x 1) (/ x 0) (+ x 2))). Pokud si chceme hodnotu vyrazu vyzvednout, tak si nadefinujeme funkci
(define (force promise) (promise))
Ktera dany prislib vyhodnoti. Jinymi slovy, nami vytvoreny prislib je ve skutecnosti anonymni funkce a funkce force, tuto funkci zavola a my ziskame hodnotu vyrazu. Toto uz zvladne malo ktery jazyk, ale slo by to resit evalem, ktery je v tomto pripade vyrazne pomalejsi a neohrabanejsi.
Pojdme dal, co kdyz chceme, aby se hodnota prislibu vypocitala jen jednou, nekam ulozila a pri kazdem zavolani force se vzala jenom ta ulozena hodnota?
Muzeme pro to pouzit nasledujici makro:
(define-macro (delay expr)
`(let ((initialized #f)
(value #f))
(lambda ()
(if initialized value
(begin
(set! initialized #t)
(set! value ,expr)
value)))))
Kdekoliv, kde se makro vyskytne, se vlozi kod ve tvaru:
(let ((initialized #f)
(value #f))
(lambda ()
(if initialized value
(begin
(set! initialized #t)
(set! value expr)
value))))
Coz udelato, ze se vytvori lexikalni prostredi obsahujici dve hodnoty (initialized a value), tento kod vrati anonymni funkci, ktera jedina muze k temto dvema hodnotam pristupovat. Zavolame-li tuto funkci, provede se overeni, jestli je tato funkce volana poprve. Pokud ano, vypocte se hodnota prislibeneho vyrazu a ulozi se do value. Pri kazdem dalsim volani je vracena jiz vypocitana hodnota.