noun kɒmpaʊnd
verb kəmˈpaʊnd
Compound is a micro structure for data used in reframe applications, based on the idea that worse is better.
It maintains a plain hash-map of indexes for your data. This has two benefits:
You can have as many indexes as you like. Some index types are built in, but adding extra ones is straight forward.
There is no query engine.
[riverford/compound "2018.01.26-1"]
For previous versions - see changelog
(require [compound.core :as c])
(def fruit
(-> (c/compound {:primary-index-def {:key :name}
:secondary-index-defs [{:key :colour}]})
(c/add-items #{{:name :strawberry
:colour :red}
{:name :raspberry
:colour :red}
{:name :banana
:colour :yellow}})))
(get (c/index fruit :name) :banana)
;; {:name :banana
;; :colour :yellow}
(get (c/index fruit :colour) :red)
;; #{{:name :strawberry
;; :colour :red}
;; {:name :raspberry
;; :colour :red}}
Full example-based documentation, covering the built-in indexes, extending with additional indexes, composite keys, handling duplicates and custom key functions, etc is found on the github pages
Over the lifetime of a re-frame app, the amount of data stored tends to grow, becoming more database-like, filling with sets of users, products, transactions and fruits.
As it grows, the maintainer of the app can either:
#(filter (comp #{:red} :colour) fruit)
in subscriptions and handlers.(1) is possibly the clearest solution, however processing time can scale both with the number of items and the number of subscriptions which perform scans. Writing filter/sequence comprehension code again and again in subscriptions and handlers can also get tedious.
(2) is a great solution for querying but is not necessarily a perfect fit for re-frame subscriptions. The datascript db is opaque to visualisation tools, and although solutions like posh exist, out of the box performance of subscriptions is typically bad because every subscription depends on the db.
Using compound is a possible third option, as close as possible to (1). It adds a convention to the maps and provides support for multiple access patterns, different cardinalities, composite keys, whilst staying open to extension.
(require '[compound.core :as c])
(def app-db {:fruit (c/compound {:primary-index-def {:key :name}
:secondary-index-defs [{:key :colour}]})
... })
(reg-sub :fruit
(fn [db]
(get db :fruit)))
(reg-sub :fruits-with-colour
:<- [:fruit]
(fn [fruit [_ selected-colour]]
(get (c/index fruit :colour) selected-colour)))
It is influenced by Christophe Grand's indexed set.
Copyright © 2017 Riverford Organic Farmers
Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.
Can you improve this documentation?Edit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close