This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
Been playing with flows, trying to mimic code from RxJava. As a result, I wrote some helping functions (just for private use). Do you think it is idiomatic Missionary ? Anything I did wrong ? https://gist.github.com/kawas44/201a4cc00efc3a912ea0fcbbeb3e77cc
I know this is a lot of work but it would help to see inline tests documenting the intended usage
Superficially, helpers like timer
and flat-map
do not really save you anything over inlining into the calling m/ap block – timer saves only one form by eliminating the m/?
at the cost of less generality; flat-map
also offers imo no obvious value over using the forking macros directly which are more expressive and superior syntax
Here are my helpers so far https://github.com/hyperfiddle/electric/blob/master/src/contrib/missionary_contrib.cljc. Leo's official comment on the matter of including higher level combinators in missionary itself is this: https://github.com/leonoel/missionary/issues/28#issuecomment-1544458866 . I think they should be at least documented (as everyone will need to derive them anyway as part of their learning journey, like in a math textbook). We also have https://github.com/hyperfiddle/electric/blob/master/src/contrib/missionary_core_async.cljc (which are badly named and need review).
just
is merely a rotated m/seed
, what is the value over just writing m/seed?
from-future
is questionable because it hardcodes the threadpool strategy [wrong] I see little value over just inlining the implementation.m/blk
. Depending on the workload, which is either compute-heavy (i.e. a slow datascript query) or IO-heavy (mostly parked and waiting on IO) you need to configure an appropriate executor.
In a way I wonder if the urge to create these (or port from RxJava, whatever) stems from a type tetris mindset (perhaps subtly originating from the Java port)? If you allow me to label this the "haskell style", that style only works if there is a checker because you end up with an explosion of combinators with slightly differing types. Part of the value of m/ap
(which has syntax for both tasks and flows) is that it is universal
(fin)
This implementation of subscribe-on
is closer to what Rx does, if I understand correctly
(defn task-subscribe-on [exec task]
(m/sp (try (m/? task)
(finally (m/? (m/via exec))))))
(defn flow-subscribe-on [exec flow]
(m/ap (try (m/?> flow)
(finally (m/? (m/via exec))))))
(defn subscribe-on!
([exec on-next flow]
(subscribe-on! exec on-next #(do %) #(do %) flow))
([exec on-next on-error flow]
(subscribe-on! exec on-next on-error #(do %) flow))
([exec on-next on-error on-complete flow]
((->> flow
(flow-subscribe-on exec)
(m/reduce (fn [_ x] (on-next x)) nil)
(task-subscribe-on exec))
on-complete on-error)))
(defn cb [x] (prn (Thread/currentThread) x))
(subscribe-on! m/cpu cb cb cb (m/seed (range 10)))
> from-future
is questionable because it hardcodes the threadpool strategy m/blk
That's fine, the thread pool is awaiting the future, not running it. It is purely IO so m/blk
is what you need here.