Měnitelná reference (ref) se vytvoří funkcí ref, její hodnotu vrací buď funkce deref, nebo makro @:
(def my-ref (ref "immutable data")) ; #'user/my-ref my-ref ; #<ref@18352d8: "immutable data"> @my-ref ; "immutable data" (deref my-ref) ; "immutable data"Pokud chceme referenci nastavit na jinou (neměnitelnou) hodnotu, slouží k tomu funkce ref-set:
(ref-set my-ref "another immutable data") ; IllegalStateException No transaction running clojure.lang.LockingTransaction.getEx (LockingTransaction.java:208)Jejda! Zapomněli jsme na transakci :-)
(dosync (ref-set my-ref "another immutable data")) ; "another immutable data" @my-ref ; "another immutable data"Pokud chceme provést čtení hodnoty a zároveň její změnu v jednom kroku (= aplikovat na hodnotu funkci), je vhodné použít funkci alter:
(dosync (alter my-ref #(apply str (reverse %)))) ; "atad elbatummi rehtona" @my-ref ; "atad elbatummi rehtona"Na reference je také možné přidat validace:
(def counter (ref 0 :validator number?)) ; #'user/counter (dosync (ref-set counter "string")) ; IllegalStateException Invalid reference state clojure.lang.ARef.validate (ARef.java:33) @counter ; 0 (dosync (ref-set counter 42)) ; 42 @counter ; 42O Refs jsem už jednou (trochu) psal. Z dnešního pohledu k tomu mám dvě výhrady:
- místo ref-set jsem měl použít alter,
- místo reference jsem měl použít atom.
Při rozhodování, jestli použít ref nebo atom je podstatné, jestli využiju transakci - v transakci můžu updatovat více referencí. Pokud budu měnit pouze jedinou hodnotu (bez vazby na cokoli jiného) je vhodnější použít atom (a o těch až někdy příště).
Žádné komentáře:
Okomentovat
Poznámka: Komentáře mohou přidávat pouze členové tohoto blogu.