Skip to content

Latest commit

 

History

History
100 lines (69 loc) · 2.97 KB

README.md

File metadata and controls

100 lines (69 loc) · 2.97 KB

leontalbot/pull

A tiny Clojure library for manipulating plain data structures a la Datomic Pull API or Om next queries.

Installation

Add the following dependency to your project.clj or build.boot file

clojars project

Usage

user=> (require '[leontalbot.pull.core :as pull])
nil

user=> (def data {:test {:a "a" :b [{:b1 "b1"} {:b1 "b1" :b2 "b2"}] :c {:c1 "c1" :c2 "c2"} :d #{"d"} :e [1 2 3]}})
#'user/data

get

get is very similar to clojure.core/get-in...

user=> (pull/get data [:test])
{:a "a", :b [{:b1 "b1"} {:b1 "b1", :b2 "b2"}], :c {:c1 "c1", :c2 "c2"}, :d #{"d"}, :e [1 2 3]}

user=> (pull/get data [:test :c])
{:c1 "c1", :c2 "c2"}

...except when the get process encounters a vector, it maps the the next selector key to every maps inside the collection...

user=> (pull/get data [:test :b])
[{:b1 "b1"} {:b1 "b1", :b2 "b2"}]

user=> (pull/get data [:test :b :b1])
("b1" "b1")

pull

pull is similar to clojure.core/select-keys...

user=> (pull/pull data [:test])
{:test {:a "a", :b [{:b1 "b1"} {:b1 "b1", :b2 "b2"}], :c {:c1 "c1", :c2 "c2"}, :d #{"d"}, :e [1 2 3]}}

...except it can handle nested selection with the hashmap syntax below:

user=> (pull/pull data [{:test [:a :b]}])
{:test {:a "a", :b [{:b1 "b1"} {:b1 "b1", :b2 "b2"}]}}

user=> (pull/pull data [{:test [:a {:b [:b1]}]}])
{:test {:a "a", :b ({:b1 "b1"} {:b1 "b1"})}}

pull also has a 3-arity version, where it accepts both get and pull queries, in that order. This allows to "get-in" the datastructure before pulling parts from it:

user=> (pull/pull data [:test] [:a :b])
{:a "a", :b [{:b1 "b1"} {:b1 "b1", :b2 "b2"}]}

user=> (pull/pull data [:test] [:a {:b [:b1]}])
{:a "a", :b ({:b1 "b1"} {:b1 "b1"})}

TODO (if necessary)

What can we do from there?

;; select all except a key?
(pull/pull data {:test [:* :e]}
;; this dissoc :e at :test

;; links?
(def test-2 {:group [[:people :id 1] [:people :id 3]] 
             :people [{:id 1 :name "Jim" :friends [[:people :id 2]]},
                      {:id 2 :name "Paul" :friends [[:people :id 1]]}
                      {:id 3 :name "Ryan" :friends [[:people :id 5]]}]})

(pull/pull test-2 [{:group [:name]}])
;; => {:group [{:name "Jim"} {:name "Ryan"}]}

References

License

Copyright © 2017 Leon Talbot

Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.