Jak měnit neměnitelné. Refs

Clojure používá neměnitelná (immutable) data/objekty. Pokud potřebujeme měnitelná (mutable) data, řeší to Clojure “měnitelnou referencí na neměnitelný objekt” :-) Jedním z prostředků, které toto řeší jsou Refs: jsou to transakční reference, které umožňují bezpečné sdílení měnitelných úložišť pomocí systému STM (Software Transactional Memory).

Měnitelná reference (ref) se vytvoří funkcí ref, její hodnotu vrací buď funkce deref, nebo makro @:

Pokud chceme referenci nastavit na jinou (neměnitelnou) hodnotu, slouží k tomu funkce ref-set:

Jejda! Zapomněli jsme na transakci :-)

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:

Na reference je také možné přidat validace:

O 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.

ref-set je vhodné použít tehdy, pokud přiřazuji novou hodnotu (nepočítám ji). alter tehdy, pokud nad hodnotou provádím nějakou funkci (např. inkrementace, přidání hodnoty do kolekce apod.).

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ě).