missionary 2025-01-20

I was a bit confused about m/amb until I read the source. I wanted to create a flow that emits values like start/chunk/end/error where there is n chunk values:

(m/amb start 
       (let [ch (m/?> 
Now I understand that amb is just a fork in an ap block that yields a value per form in its body

I have a project in claude with the missionary docs and sources + wiki and it is still quite confused by amb, it uses it as if it emits something:

(m/? (m/reduce                    
       (fn [acc chunk]
         (m/amb chunk) ;; whaaaaat ?                      
         (str acc chunk))
       ""                    
       <flow))

to achieve the above (emit accumulated chunks on every chunk then return the full acc at the end) I ended up doing:

(m/amb (m/?> (m/reductions str "" <flow)) (m/reduce str "" <flow))

mhm with my solution I realize now that <flow is run twice

you can share with m/signal or m/stream

m/reductions already emits the final reduction, do you want to duplicate it ?

yes I emit :event/type :chunk and on the last one I want to emit :event/type :done as well

I would use m/eduction with a custom transducer emitting a value in the completion stage

well the last value of the m/reductions flow is actually the same as the result of m/reduce

I meant this :

(defn duplicate-last [rf]
  (let [last (object-array 1)]
    (fn
      ([] (rf))
      ([r] (rf (rf r (aget last 0))))
      ([r x] (rf r (aset last 0 x))))))

(m/eduction duplicate-last (m/reductions str "" <flow))

yeah with some tuning I could make it return my done event

but maybe I should just do something more idiomatic

@leonoel I have a stupid question on the object-array which I see a lot also on electric code. You use it like an atom, but without the overhead of an atom. So what you really want Is to store a muteable value. Is this about correct? Is this the most performant was of doing it? Thanks!

Yes, object-array is the simplest way to allocate heap memory with no synchronization overhead. Performance wise it is equivalent to an object with mutable fields, the JVM is very good at optimizing that. I generally prefer arrays over objects because the clojure syntax is much more convenient especially if you want to port it to cljs. An object array is really a cons cell of arbitrary size, it's a very lispy concept when you think about it

BTW it is not a stupid question

👍🏻 1
💯 2

Thanks so much!

I have written a highly experimental library to expose clojure missionary flows and tasks from a server and consume them in the browser in clojurescript. A react hook for uix is included. By far not as integrated as electric, but perhaps useful https://github.com/pink-gorilla/flowy

👏 3

Reagent example is added as well.