Skip to content

Commit fe0f293

Browse files
committed
Pass a single arg to :output and :live?
We couldn't think of a use-case for passing in the old output value as a separate arg. Same for passing the db to the live function. If no inputs are declared, then we pass the entire app-db instead. That means we can do really concise flows, like: {:id :bedroom-area :output (fn [{{:keys [width height]} :bedroom :as db}] (* width height))}
1 parent 1e86b9f commit fe0f293

File tree

2 files changed

+23
-20
lines changed

2 files changed

+23
-20
lines changed

docs/Flows.md

+11-11
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,16 @@ Here's a basic `flow`. It describes how to derive the area of a room from its di
3131
{:id :room-area
3232
:inputs {:w [:room :width]
3333
:h [:room :length]}
34-
:output (fn calc-area [previous-area {:keys [w h] :as inputs}]
34+
:output (fn calc-area [{:keys [w h] :as inputs}]
3535
(* w h))
3636
:path [:room :area]}
3737
</div>
3838

3939
- **`:id`** - uniquely identifies this flow.
4040
- **`:inputs`** - a map of `app-db` paths to observe for changes.
41-
- **`:output`** - calculates the new derived value. Accepts the previous result, and a map of input values.
41+
- **`:output`** - calculates the new derived value.
42+
- Takes a map of resolved inputs.
43+
- Simply takes `app-db` if there are no inputs.
4244
- **`:path`** - denotes *where* the derived value should be stored.
4345

4446
Every event, when the values of `:inputs` change, `:output` is run, and the result is stored in `app-db` at `:path`.
@@ -90,8 +92,7 @@ Now the interesting part, we use `reg-flow`:
9092
{:id :garage-area
9193
:inputs {:w [:garage :width]
9294
:h [:garage :length]}
93-
:output (fn area [previous-area {:keys [w h] :as inputs}]
94-
(* w h))
95+
:output (fn [{:keys [w h]}] (* w h))
9596
:path [:garage :area]})
9697

9798
(rf/reg-flow garage-area-flow)
@@ -252,7 +253,7 @@ Here's a flow using two other flows as inputs: `::kitchen-area` and `::living-ro
252253
{:id :main-room-ratio
253254
:inputs {:kitchen (rf/flow-input ::kitchen-area)
254255
:living-room (rf/flow-input ::living-room-area)}
255-
:output (fn [_ {:keys [kitchen living-room]}]
256+
:output (fn [{:keys [kitchen living-room]}]
256257
(/ kitchen living-room))
257258
:path [:ratios :main-rooms]}
258259
</div>
@@ -286,11 +287,10 @@ Here's another room area flow:
286287
{:id :kitchen-area
287288
:inputs {:w [:kitchen :width]
288289
:h [:kitchen :length]}
289-
:output (fn area [previous-area {:keys [w h] :as inputs}]
290-
(* w h))
290+
:output (fn [{:keys [w h]}] (* w h))
291291
:path [:kitchen :area]
292292
:live-inputs {:tab [:tab]}
293-
:live? (fn [db {:keys [tab]}]
293+
:live? (fn [{:keys [tab]}]
294294
(= tab :kitchen))})
295295
</div>
296296

@@ -478,7 +478,7 @@ It builds a flow that validates our item list against the requirements:
478478
:path [::error-state]
479479
:inputs {:items [::items]
480480
:tab (rf/flow-input :current-tab)}
481-
:output (fn [_ {:keys [items]}]
481+
:output (fn [{:keys [items]}]
482482
(let [ct (count items)]
483483
(cond
484484
(> ct max-items) :too-many
@@ -738,14 +738,14 @@ Even though `::num-balloons-to-fill-kitchen` depends on other flows, we can acce
738738
{:id ::kitchen-volume
739739
:inputs {:area [:kitchen :area]
740740
:height [:kitchen :height]}
741-
:output (fn [_ {:keys [area height]}]
741+
:output (fn [{:keys [area height]}]
742742
(* area height))
743743
:path [:kitchen :volume]})
744744

745745
(rf/reg-flow
746746
{:id ::num-balloons-to-fill-kitchen
747747
:inputs {:volume ::kitchen-volume}
748-
:output (fn [_ {:keys [volume]}]
748+
:output (fn [{:keys [volume]}]
749749
(let [std-balloon-volume 2.5]
750750
(/ volume std-balloon-volume)))})
751751

src/re_frame/flow/alpha.cljc

+12-9
Original file line numberDiff line numberDiff line change
@@ -146,26 +146,29 @@
146146
" which has no associated handler. Ignoring.")))
147147
(update-in ctx [:effects :fx] (partial remove (set flow-fx)))))))}))
148148

149+
(defn resolve-inputs [db inputs]
150+
(if (empty? inputs) db (u/map-vals (partial get-output db) inputs)))
151+
149152
(defn update-flow [ctx {:as flow
150153
:keys [path init cleanup live? inputs live-inputs output id]
151154
::keys [cleared?]}]
152155
(let [{::keys [new?]} (meta flow)
153156
old-db (get-coeffect ctx :db)
154157
new-db (or (get-effect ctx :db) old-db)
155-
id->old-live-input (u/map-vals (partial get-output old-db) live-inputs)
156-
id->live-input (u/map-vals (partial get-output new-db) live-inputs)
157-
id->old-input (u/map-vals (partial get-output old-db) inputs)
158-
id->input (u/map-vals (partial get-output new-db) inputs)
158+
id->old-live-input (resolve-inputs old-db live-inputs)
159+
id->live-input (resolve-inputs new-db live-inputs)
160+
id->old-input (resolve-inputs old-db inputs)
161+
id->input (resolve-inputs new-db inputs)
159162
dirty? (not= id->input id->old-input)
160-
bardo [(cond new? :new (live? old-db id->old-live-input) :live :else :dead)
161-
(cond cleared? :cleared (live? new-db id->live-input) :live :else :dead)]
163+
bardo [(cond new? :new (live? id->old-live-input) :live :else :dead)
164+
(cond cleared? :cleared (live? id->live-input) :live :else :dead)]
162165
update-db (case bardo
163166
[:new :live] #(do (swap! flows update id vary-meta dissoc ::new?)
164-
(update-in (init % path) path output id->input))
167+
(assoc-in (init % path) path (output id->input)))
165168
[:live :cleared] #(cleanup % path)
166-
[:live :live] #(cond-> % dirty? (update-in path output id->input))
169+
[:live :live] #(cond-> % dirty? (assoc-in path (output id->input)))
167170
[:live :dead] #(cleanup % path)
168-
[:dead :live] #(update-in (init % path) path output id->input)
171+
[:dead :live] #(assoc-in (init % path) path (output id->input))
169172
identity)]
170173
(update-effect ctx :db (fnil update-db (get-coeffect ctx :db)))))
171174

0 commit comments

Comments
 (0)