state unified state

Author: Chris Zheng  (z@caudate.me)
Date: 27 November 2018
Repository: https://github.com/zcaudate/hara
Version: 3.0.2

1    Introduction

hara.state provides baseline stateful datastructures.

1.1    Installation

Add to project.clj dependencies:

[hara/base "3.0.2"]

All functions are in the hara.state namespace.

 (use (quote hara.state))

2    API



cache ^

creates a cache with the following properties

v 3.0
(defn cache
  ([data]
   (cache data {}))
  ([data {:keys [tag display type] :as metadata
          :or {type :atom}}]
   (try
     (let [cls   (common/container type)
           state (common/create cls data nil)]
       (Cache. state (assoc metadata :type type)))
     (catch java.lang.IllegalArgumentException e
       (throw (ex-info "Invalid cache type:"
                       {:type type
                        :options (set (keys (.getMethodTable protocol.state/-container-state)))}))))))
link
(-> (cache {} {:tag "stuff" :type :ref}) (.state)) => clojure.lang.Ref (str (cache {:a 1 :b 2} {:type :agent})) => "#cache:agent{:a 1, :b 2}"

clone ^

clones the state object

v 3.0
(defn clone
  ([obj]
   (clone obj nil))
  ([obj opts]
   (or (error/suppress (protocol.state/-clone-state (atom {}) {}))
       (let [data (protocol.state/-get-state obj opts)]
         (create (clojure.core/type obj) data opts)))))
link
(-> (state/container :volatile) (state/create 2) (state/clone)) => volatile?

copy ^

copies the value of one state to another

v 3.0
(defn copy
  ([source sink]
   (copy source sink nil))
  ([source sink opts]
   (let [data (protocol.state/-get-state source opts)]
     (protocol.state/-set-state sink data opts)
     source)))
link
(def -a- (ref nil)) (state/copy (atom 1) -a-) @-a- => 1

create ^

creates a state of a particular type

v 3.0
(defn create
  ([class data]
   (create class data nil))
  ([class data opts]
   (protocol.state/-create-state class data opts)))
link
((juxt deref type) (state/create clojure.lang.Atom 1)) => [1 clojure.lang.Atom]

defcache ^

defines a cache

v 3.0
(defmacro defcache
  [name & [doc? attrs? [type metadata :as opts?]]]
  (let [[doc attrs {:keys [refresh] :as opts}]
        (macro/create-args [doc? attrs? opts?])

        [type metadata]
        (cond (nil? opts)
              [:atom {}]
              
              (vector? opts) opts
              
              :else
              (throw (ex-info "Cannot recognise option." {:opts opts})))
        body `(cache {} (assoc ~metadata :type ~type))]
    (if (or refresh
            (not (resolve name)))
      (macro/create-def-form name doc attrs () body))))
link
(defcache -a-) (.state -a-) => clojure.lang.Atom (defcache -b- [:volatile {:tag "hello"}]) (.state -b-) => volatile?

empty ^

empties the state, extensible through the IStateSet protocol

v 3.0
(defn empty
  ([obj] (empty obj nil))
  ([obj opts]
   (protocol.state/-empty-state obj opts)
   obj))
link
(let [a (atom 1)] (state/empty a) @a) => nil

get ^

like deref but is extensible through the IStateGet protocol

v 3.0
(defn get
  ([obj] (get obj nil))
  ([obj opts]
   (protocol.state/-get-state obj opts)))
link
(state/get (atom 1)) => 1 (state/get (ref 1)) => 1

set ^

like reset! but is extensible through the IStateSet protocol

v 3.0
(defn set
  ([obj v] (set obj v nil))
  ([obj v opts]
   (protocol.state/-set-state obj v opts)
   obj))
link
(let [a (atom nil)] (state/set a 1) @a) => 1

update ^

like swap! but is extensible through the IStateSet protocol

v 3.0
(defn update
  ([obj f]
   (protocol.state/-update-state obj f [] nil)
   obj)
  ([obj f & args]
   (protocol.state/-update-state obj f args nil)
   obj))
link
(let [a (atom 0)] (state/update a + 1) @a) => 1

update-apply ^

like swap! but is extensible through the IStateSet protocol

v 3.0
(defn update-apply
  ([obj f args]
   (update-apply obj f args nil)
   obj)
  ([obj f args opts]
   (protocol.state/-update-state obj f args opts)
   obj))
link
(let [a (atom 0)] (state/update-apply a + [1 2 3]) @a) => 6