hara.group generic typed collections

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

1    Introduction

hara.group allow definition of collections of the same type of items.

1.1    Installation

Add to project.clj dependencies:

[im.chit/hara.group "2.5.10"]

All functionality is in the hara.group namespace:

(use 'hara.group)

2    Index

3    API

3.1    Definitions

Groups and items are defined as follows:



defgroup ^

creates a group of items

v 2.2
(defmacro defgroup
  ([name] `(defgroup ~name {}))
  ([name m]
   `(def ~name (-> ~m
                   (map/merge-nil {:var (var ~name)
                                   :tag ~(keyword (str name))})
                   (group)))))
link
(defgroup people {:tag :people :constructor map->Person :items [{:name :andy} {:name :bob}]}) => (comp group? deref)

defitem ^

adds an item to the group

v 2.2
(defmacro defitem
  [group data]
  `(do (add-item ~group ~data)
       (:var ~group)))
link
(-> (defitem people {:name :chris}) deref list-items) => [:andy :bob :chris]

3.2    Methods

Methods for changing items in the defined group are:



add-item ^

adds an item to the group

v 2.2
(defn add-item
  [{:keys [constructor key] :as group} data]
  (let [new (constructor data)
        tag (key new)
        ngroup (assoc-in group [:items tag] new)]
    (alter-var-root (:var group) (fn [_] ngroup))))
link
(-> (add-item people {:name :chris}) (list-items)) => [:andy :bob :chris]

append-items ^

appends a set of data to the group

v 2.2
(defn append-items
  [{:keys [constructor key items] :as group} data]
  (update-in group [:items]
             (fn [items]
               (cond (vector? data)
                     (reduce (fn [out item]
                               (assoc out (key item) (constructor item)))
                             items
                             data)

                     (map? data)
                     (reduce-kv (fn [out k item]
                                  (assoc out k (constructor (assoc item key k))))
                                items
                                data)

                     :else items))))
link
(-> (append-items people [{:name :dave} {:name :erin}]) (list-items)) => [:andy :bob :dave :erin]

find-item ^

finds an item based on the given key

v 2.2
(defn find-item
  [{:keys [items] :as group} tag]
  (get items tag))
link
(find-item people :andy) => {:name :andy}

group ^

creates a group from a map

v 2.2
(defn group
  [m]
  (let [{:keys [constructor key items] :as m} (map/merge-nil m {:key :name
                                                          :constructor identity})]
    (-> (dissoc m :items)
        (append-items items)
        (map->Group))))
link
(group {:tag :hello}) => #(-> % :tag (= :hello))

group? ^

checks to see if an element is a group

v 2.2
(defn group?
  [x]
  (instance? hara.group.Group x))
link
(group? people) => true

install-items ^

reads a set of data from a resource and loads it into the group

v 2.2
(defn install-items
  [group file]
  (let [data (-> file
                 slurp
                 read-string)]
    (append-items group data)))
link
(-> (install-items people (java.io.StringReader. "[{:name :dave} {:name :erin}]")) (list-items)) => [:andy :bob :dave :erin]

list-items ^

returns a list of keys to items in the group

v 2.2
(defn list-items
  [{:keys [items] :as group}]
  (sort (keys items)))
link
(list-items people) => [:andy :bob]

remove-item ^

removes items based on the key

v 2.2
(defn remove-item
  [group tag]
  (let [ngroup (update-in group [:items] dissoc tag)]
    (alter-var-root (:var group) (fn [_] ngroup))))
link
(-> (remove-item people :chris) (list-items)) => [:andy :bob]