To je zajimava otazka a dekuji za ni. Plati, ze prvky lazy sekvence zustanou v pameti tak dlouho, dokud na tuto sekvenci existuje reference, tj. (kdyz to prevedu do Javovske reci) existuje promenna ci parametr, ktery referencuje objekty typu sekvence. Funguje to tak, ze napriklad pri druhem volani funkce "nth" nebo "take" se uz prvky vyhodnotit nemusi, ovsem predpoklada se, ze se pouzivaji ciste funkce bez vedlejsiho efektu, coz rand neni :-) [nekde je ulozen predchozi stav generatoru pseudonahodnych cisel, ktery se volanim (rand) zmeni].
Asi uvedu i priklad, doufam, ze projde formatovani. Mejme jednoduchou funkci:
(defn increment
[x]
(do
(println "computing " x)
(inc x)))
u ni je zajimave, ze jako vedlejsi efekt pri svem zavolani "neco" vypise na stdout.
Ted vytvorime lazy sekvenci:
(def mysequence (map increment (range 1 10)))
... a nic se nevypsalo! protoze Clojure je liny lazy sekvenci vyhodnocovat - ostatne ani nemusi, alespon prozatim :)
Ziskame prvni 4 prvky:
(take 4 mysequence) (computing 1 computing 2 computing 3 computing 4 computing 5 computing 6 computing 7 computing 8 computing 9 2 3 4 5)
ted doslo k vyhodnoceni sekvence, coz prozradi printy - vedlejsi efekt
A co kdyz "take" zavolame znovu?:
(take 4 mysequence) (2 3 4 5)
nic se krome navratove hodnoty take nevypsalo = uz se nase funkce nevola protoze mame vysledky "cachovany"
To sice vypadá zajímavě, ale nelíbí se mi, že se to dělá automaticky a tímpádem programátor musí myslet na to, jestli generátor obsahuje nějaké vedlejší efekty nebo vstupy, nebo ne.
Co kdybych chtěl např. lazy sekvenci, která by mi vracela *aktuální* obsah souboru? Dalo by se to nějak udělat ("vypnout" cachování)?
jeste pridam zajimavou informaci, co jsem pred chvili dohledal: "Rich Hickey, the designer of Clojure, responded by saying that he had already experimented with uncached lazy sequences, and that such a choice causes a different set of problems with performance problems and code breaking – problems which he found to be even more common than the ones I've raised here."
Ten post vypadá zajímavě, teď nemám čas/chuť to číst, ale určitě se k tomu vrátím, včetně toho vlákna v konfeře Clojure, kde tohle Hickey říká. Dost by mě totiž zajímalo, čím tohle tvrzení podkládá.
Autor postu má argumenty (imho) silný a logický, přesně tohle mě právě napadlo taky:
First, it's easier to convert an uncached sequence to a cached sequence than vice versa. Second, if you forget to cache something that should be cached, it's merely a performance optimization problem, but if you forget to uncache something that needs to be cached, your program can crash. So, it's safer if the language defaults to uncached.
Přijde mi, že by bylo lepší použít uncached sekvence a k tomu cacheovací wrapper, který by programátor mohl a nemusel použít, podle vlastního uvážení.