hara.common primitives declarations and functions

Author: Chris Zheng  (z@caudate.me)
Date: 29 June 2017
Repository: https://github.com/zcaudate/hara
Version: 2.5.10

hara.common are a set of primitive declarations and functions that extend on top of clojure.core and are used by many of the other namespaces in the hara ecosystem.

1    common.checks

Add to project.clj dependencies:

[im.chit/hara.common.checks "2.5.10"]

hara.common.checks contain basic type predicates that are not included in the clojure.core namespace.



agent? ^

returns `true` if `x` is of type `clojure.lang.Agent`.

v 2.0
(defn agent?
  [obj]
  (instance? clojure.lang.Agent obj))
link
(agent? (agent nil)) => true

atom? ^

returns `true` if `x` is of type `clojure.lang.Atom`.

v 2.0
(defn atom?
  [obj]
  (instance? clojure.lang.Atom obj))
link
(atom? (atom nil)) => true

bigdec? ^

returns `true` if `x` is of type `java.math.BigDecimal`.

v 2.0
(defn bigdec?
  [x] (instance? java.math.BigDecimal x))
link
(bigdec? 1M) => true (bigdec? 1.0) => false

bigint? ^

returns `true` if `x` is of type `clojure.lang.BigInt`.

v 2.0
(defn bigint?
  [x] (instance? clojure.lang.BigInt x))
link
(bigint? 1N) => true (bigint? 1) => false

boolean? ^

returns `true` if `x` is of type `java.lang.Boolean`.

v 2.0
(defn boolean?
  [x] (instance? java.lang.Boolean x))
link
(boolean? true) => true (boolean? false) => true

bytes? ^

returns `true` if `x` is a primitive `byte` array.

v 2.0
(defn bytes?
  [^Object x]
  (= (Class/forName "[B")
     (.getClass x)))
link
(bytes? (byte-array 8)) => true

double? ^

returns `true` if `x` is of type `java.lang.Double`.

v 2.1
(defn double?
  [x] (instance? java.lang.Double x))
link
(double? 1) => false (double? (double 1)) => true

hash-map? ^

returns `true` if `x` implements `clojure.lang.APersistentMap`.

v 2.0
(defn hash-map?
  [x] (instance? clojure.lang.APersistentMap x))
link
(hash-map? {}) => true (hash-map? []) => false

ideref? ^

returns `true` if `x` is of type `java.lang.IDeref`.

v 2.0
(defn ideref?
  [obj]
  (instance? clojure.lang.IDeref obj))
link
(ideref? (atom 0)) => true (ideref? (promise)) => true (ideref? (future)) => true

instant? ^

returns `true` if `x` is of type `java.util.Date`.

v 2.0
(defn instant?
  [x] (instance? java.util.Date x))
link
(instant? (java.util.Date.)) => true

iobj? ^

checks if a component is instance of clojure.lang.IObj

v 2.5
(defn iobj?
  [x]
  (instance? clojure.lang.IObj x))
link
(iobj? 1) => false (iobj? {}) => true

iref? ^

returns `true` if `x` is of type `clojure.lang.IRef`.

v 2.0
(defn iref?
  [obj]
  (instance? clojure.lang.IRef obj))
link
(iref? (atom 0)) => true (iref? (ref 0)) => true (iref? (agent 0)) => true (iref? (promise)) => false (iref? (future)) => false

lazy-seq? ^

returns `true` if `x` implements `clojure.lang.LazySeq`.

v 2.1
(defn lazy-seq?
  [x] (instance? clojure.lang.LazySeq x))
link
(lazy-seq? (map inc [1 2 3])) => true (lazy-seq? ()) => false

long? ^

returns `true` if `x` is of type `java.lang.Long`.

v 2.0
(defn long?
  [x] (instance? java.lang.Long x))
link
(long? 1) => true (long? 1N) => false

promise? ^

returns `true` is `x` is a promise

v 2.0
(defn promise?
  [^Object obj]
  (let [^String s (.getName ^Class (type obj))]
    (.startsWith s "clojure.core$promise$")))
link
(promise? (promise)) => true (promise? (future)) => false

ref? ^

returns `true` if `x` is of type `clojure.lang.Ref`.

v 2.0
(defn ref?
  [obj]
  (instance? clojure.lang.Ref obj))
link
(ref? (ref nil)) => true

regex? ^

returns `true` if `x` implements `clojure.lang.IPersistentMap`.

v 2.0
(defn regex?
  [x] (instance? java.util.regex.Pattern x))
link
(regex? #"d+") => true

thread? ^

returns `true` is `x` is a thread

v 2.2
(defn thread?
  [obj]
  (instance? java.lang.Thread obj))
link
(thread? (Thread/currentThread)) => true

type-checker ^

returns the checking function associated with `k`

v 2.0
(defn type-checker
  [k]
  (resolve (symbol (str (name k) "?"))))
link
(type-checker :string) => #'clojure.core/string? (require '[hara.common.checks :refer [bytes?]]) (type-checker :bytes) => #'hara.common.checks/bytes?

uri? ^

returns `true` if `x` is of type `java.net.URI`.

v 2.0
(defn uri?
  [x] (instance? java.net.URI x))
link
(uri? (java.net.URI. "http://www.google.com")) => true

url? ^

returns `true` if `x` is of type `java.net.URL`.

v 2.2
(defn url?
  [x] (instance? java.net.URL x))
link
(url? (java.net.URL. "file:/Users/chris/Development")) => true

uuid? ^

returns `true` if `x` is of type `java.util.UUID`.

v 2.0
(defn uuid?
  [x] (instance? java.util.UUID x))
link
(uuid? (java.util.UUID/randomUUID)) => true

2    common.error

Add to project.clj dependencies:

[im.chit/hara.common.error "2.5.10"]

hara.common.error contain simple macros for throwing and processing errors.



error ^

throws an exception when called.

v 2.0
(defmacro error
  [e & [opt? & more]]
  `(if (instance? Throwable ~e)
     (throw (Exception. (str ~opt? ~@more) ~e))
     (throw (Exception. (str ~e ~opt? ~@more)))))
link
(error "This is an error") => (throws Exception "This is an error") (error (Exception. "This is an error") "This is a chained error") => (throws Exception "This is a chained error")

suppress ^

suppresses any errors thrown in the body.

v 2.0
(defmacro suppress
  ([body]
     `(try ~body (catch Throwable ~'t)))
  ([body catch-val]
     `(try ~body (catch Throwable ~'t
                   (cond (fn? ~catch-val)
                         (~catch-val ~'t)
                         :else ~catch-val)))))
link
(suppress (error "Error")) => nil (suppress (error "Error") :error) => :error (suppress (error "Error") (fn [e] (.getMessage e))) => "Error"

3    common.hash

Add to project.clj dependencies:

[im.chit/hara.common.error "2.5.10"]

hara.common.hash contain methods for working with object hashes.



hash-label ^

returns a keyword repesentation of the hash-code. For use in generating internally unique keys

v 2.0
(defn hash-label
  ([^Object obj] (str "__" (.hashCode obj) "__"))
  ([^Object obj & more]
   (->> (map (fn [^Object x] (.hashCode x)) (cons obj more))
        (string/join "_")
        (format "__%s__"))))
link
(hash-label 1) => "__1__" (hash-label "a" "b" "c") => "__97_98_99__" (hash-label "abc") => "__96354__"

4    common.primitives

Add to project.clj dependencies:

[im.chit/hara.common.primitives "2.5.10"]

hara.common.primitives contain constructs that are not included in the clojure.core namespace.

hara.common.primitives



^

returns `false` for any combination of input `args`

v 2.0
(defn F
  [& args] false)
link
(F) => false (F :hello) => false (F 1 2 3) => false

NIL ^

returns `nil` for any combination of input `args`

v 2.0
(defn NIL
  [& args] nil)
link
(NIL) => nil (NIL :hello) => nil (NIL 1 2 3) => nil

^

returns `true` for any combination of input `args`

v 2.0
(defn T
  [& args] true)
link
(T) => true (T :hello) => true (T 1 2 3) => true

instant ^

returns a `java.util.Date` object

v 2.0
(defn instant
  ([] (java.util.Date.))
  ([^Long val] (java.util.Date. val)))
link
(instant) => #(instance? java.util.Date %) (instant 0) => #inst "1970-01-01T00:00:00.000-00:00"

queue ^

returns a `clojure.lang.PersistentQueue` object.

v 2.0
(defn queue
  ([] (clojure.lang.PersistentQueue/EMPTY))
  ([x] (conj (queue) x))
  ([x & xs] (apply conj (queue) x xs)))
link
(def a (queue 1 2 3 4)) (pop a) => [2 3 4]

uri ^

returns a `java.net.URI` object

v 2.0
(defn uri
  [path] (java.net.URI/create path))
link
(uri "http://www.google.com") => #(instance? java.net.URI %)

uuid ^

returns a `java.util.UUID` object

v 2.0
(defn uuid
  ([] (java.util.UUID/randomUUID))
  ([id]
     (cond (string? id)
           (java.util.UUID/fromString id)
           (checks/bytes? id)
           (java.util.UUID/nameUUIDFromBytes id)
           :else (error id " can only be a string or byte array")))
  ([^Long msb ^Long lsb]
     (java.util.UUID. msb lsb)))
link
(uuid) => #(instance? java.util.UUID %) (uuid "00000000-0000-0000-0000-000000000000") => #uuid "00000000-0000-0000-0000-000000000000"

5    common.state

Add to project.clj dependencies:

[im.chit/hara.common.state "2.5.10"]

hara.common.state contain extensible methods for manipulating stateful datastructures:

hara.common.state



dispatch ^

updates the value contained within a container using another thread.

v 2.1
(defn dispatch
  [ref f & args]
  (future
    (apply update ref f args)))
link
(def res (state/dispatch (atom 0) (fn [x] (inc x)))) res => future? @res => atom? @@res => 1

empty ^

empties the state, extensible through the IStateSet protocol

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

get ^

like deref but is extensible through the IStateGet protocol

v 2.1
(defn get
  ([obj] (get obj nil))
  ([obj opts]
     (-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 2.1
(defn set
  ([obj v] (set obj nil v))
  ([obj opts v]
     (-set-state obj opts v)
     obj))
link
(let [a (atom nil)] (state/set a 1) @a) => 1

update ^

like swap! but is extensible through the IStateSet protocol

v 2.1
(defn update
  ([obj f]
     (update obj nil f [])
     obj)
  ([obj opts? f & args]
     (if (nil? opts?)
       (-update-state obj nil f (first args))
       (let [[opts f args]
             (if (fn? opts?)
               [nil opts? (cons f args)]
               [opts? f args])]
         (-update-state obj opts f args)
         obj))))
link
(let [a (atom 0)] (state/update a + 1) @a) => 1

6    common.string

Add to project.clj dependencies:

[im.chit/hara.common.string "2.5.10"]

hara.common.string contain extensible methods for string manipulation:

hara.common.string



from-string ^

meta information of keywords and symbols

v 2.1
(defmulti from-string
  (fn [meta string] (or (:type meta) meta)))
link
(from-string {:type clojure.lang.Symbol} "hello/world") => 'hello/world (from-string {:type clojure.lang.Keyword} "hello/world") => :hello/world

to-meta ^

meta information of keywords and symbols

v 2.1
(defn to-meta
  [x]
  (-to-string-meta x))
link
(to-meta 'hello/world) => {:type clojure.lang.Symbol} (to-meta :hello/world) => {:type clojure.lang.Keyword}

to-string ^

converts symbols and keywords to string representation

v 2.1
(defn to-string
  ^String [x]
  (-to-string x))
link
(to-string 'hello/world) => "hello/world" (to-string :hello/world) => "hello/world"

7    common.watch

Add to project.clj dependencies:

[im.chit/hara.common.watch "2.5.10"]

hara.common.watch contain extensible methods for observation of state:

hara.common.watch



add ^

adds a watch function through the IWatch protocol

v 2.1
(defn add
  ([obj f] (add obj nil f nil))
  ([obj k f] (add obj k f nil))
  ([obj k f opts]
     (-add-watch obj k f opts)))
link
(def subject (atom nil)) (def observer (atom nil)) (watch/add subject :follow (fn [_ _ _ n] (reset! observer n))) (reset! subject 1) @observer => 1 ;; options can be given to either transform ;; the current input as well as to only execute ;; the callback if there is a difference. (def subject (atom {:a 1 :b 2})) (def observer (atom nil)) (watch/add subject :clone (fn [_ _ p n] (reset! observer n)) {:select :b :diff true}) (swap! subject assoc :a 0) ;; change in :a does not @observer => nil ;; affect watch (swap! subject assoc :b 1) ;; change in :b does @observer => 1

clear ^

clears all watches form the object

v 2.1
(defn clear
  ([obj] (clear obj nil))
  ([obj opts]
     (let [watches (list obj opts)]
       (doseq [k (keys watches)]
         (remove obj k opts)))))
link
(def subject (atom nil)) (do (watch/add subject :a (fn [_ _ _ n])) (watch/add subject :b (fn [_ _ _ n])) (watch/clear subject) (watch/list subject)) => {}

copy ^

copies watches from one object to another

v 2.1
(defn copy
  ([to from] (copy to from nil))
  ([to from opts]
     (let [watches (list from opts)]
       (set to watches opts))))
link
(def obj-a (atom nil)) (def obj-b (atom nil)) (do (watch/set obj-a {:a (fn [_ _ _ n]) :b (fn [_ _ _ n])}) (watch/copy obj-b obj-a) (watch/list obj-b)) => (contains {:a fn? :b fn?})

list ^

lists watch functions through the IWatch protocol

v 2.1
(defn list
  ([obj] (list obj nil))
  ([obj opts] (-list-watch obj opts)))
link
(def subject (atom nil)) (do (watch/add subject :a (fn [_ _ _ n])) (watch/add subject :b (fn [_ _ _ n])) (watch/list subject)) => (contains {:a fn? :b fn?})

remove ^

removes watch function through the IWatch protocol

v 2.1
(defn remove
  ([obj]   (remove obj nil nil))
  ([obj k] (remove obj k nil))
  ([obj k opts] (-remove-watch obj k opts)))
link
(def subject (atom nil)) (do (watch/add subject :a (fn [_ _ _ n])) (watch/add subject :b (fn [_ _ _ n])) (watch/remove subject :b) (watch/list subject)) => (contains {:a fn?})

set ^

sets a watch in the form of a map

v 2.1
(defn set
  ([obj watches] (set obj watches nil))
  ([obj watches opts]
     (doseq [[k f] watches]
       (add obj k f opts))
     (list obj opts)))
link
(def obj (atom nil)) (do (watch/set obj {:a (fn [_ _ _ n]) :b (fn [_ _ _ n])}) (watch/list obj)) => (contains {:a fn? :b fn?})