Skip to content

Instantly share code, notes, and snippets.

@jstaffans
Last active September 1, 2015 06:49
Show Gist options
  • Save jstaffans/fd8e6683cf9cb24ebdde to your computer and use it in GitHub Desktop.
Save jstaffans/fd8e6683cf9cb24ebdde to your computer and use it in GitHub Desktop.
Nested data sources with muse
;; Trying to traverse an AST whose root is a list
(defrecord ParentDS []
muse/DataSource
(fetch [_]
(async/go [{:id 1 :name "Parent 1"} {:id 2 :name "Parent 2"}]))
muse/LabeledSource
(resource-id [_]
:some-label))
(defrecord ChildDS [parent]
muse/DataSource
(fetch [_]
(async/go
{:belongs-to (:name parent)}))
muse/LabeledSource
(resource-id [_]
parent))
(muse/run!! (muse/traverse
(fn [parent]
(muse/fmap
(fn [child] (assoc parent :child child))
(ChildDS. parent)))
(ParentDS.)))
=> [{:id 1, :name "Parent 1", :child #muse.core.MuseDone{:value {:belongs-to "Parent 1"}}} {:id 2, :name "Parent 2", :child #muse.core.MuseDone{:value {:belongs-to "Parent 2"}}}]
;; So far so good. But how do I extend it beyond "(muse/value child)", ie for grandchildren?
(defrecord GrandchildDS [parent]
muse/DataSource
(fetch [_]
(async/go
{:grandchild-of (:belongs-to parent)}))
muse/LabeledSource
(resource-id [_]
parent))
(muse/run!!
(muse/traverse
(fn [parent] ;; {:id 1 :name "Parent 1"}
(muse/flat-map
(fn [child] ;; {:belongs-to "Parent 1"}
(muse/fmap
(fn [grandchild] ;; {:grandchild-of "Parent 1"}
;; all values are already evaluated here
(assoc parent :child (muse/value (assoc child :grandchild grandchild))))
(GrandchildDS. child)))
(ChildDS. parent)))
(ParentDS.)))
=> [{:id 1, :name "Parent 1", :child {:belongs-to "Parent 1", :grandchild {:grandchild-of "Parent 1"}}} {:id 2, :name "Parent 2", :child {:belongs-to "Parent 2", :grandchild {:grandchild-of "Parent 2"}}}
;; 1. assoc happens only at end, when all values are known.
;; 2. muse/flat-map tells muse we need more data to build a value.
;; muse/value is a wrapper for data ready to be used, so the above is equivalent to:
(muse/run!!
(muse/traverse
(fn [parent] ;; {:id 1 :name "Parent 1"}
(muse/flat-map
(fn [child] ;; {:belongs-to "Parent 1"}
(muse/flat-map
(fn [grandchild] ;; {:grandchild-of "Parent 1"}
;; all values are already evaluated here
(muse/value (assoc parent :child (assoc child :grandchild grandchild))))
(GrandchildDS. child)))
(ChildDS. parent)))
(ParentDS.)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment