missionary

leonoel 2025-02-27T12:31:52.010829Z

released b.44 - fixes a major concurrency bug in the propagation algorithm (`m/memo`, m/stream, m/signal)

👍 8
👍🏻 1
zihao 2025-02-27T04:13:26.129549Z

I read https://gist.github.com/dustingetz/d3fb5338b43ef86df5f97387f1d5e249#file-await_promise-clj. it mentions the ambiguity > Do you want to await the result of an already running promise > or do you want to run the process of the promise when the task is run? and the task await-promise return should be the first task? since p is not under control. but what if I want the second kind of task? the senario is I have third party lib provide many functions that return promise/future. I want to wrap them in task, and get referential transparency, I can run the task multiple time to get multiple effects

(let [task (promise->task (third-party-f))]
    (m/? 
     (m/? task) ;; run underlying effect
     (m/? task) ;; run underlying effect again
     ))

leonoel 2025-02-27T10:43:06.003099Z

Here is an example with CompletableFuture

(defn from-cf-call [->cf]
  (fn [s f]
    (try (let [^CompletableFuture cf (->cf)]
           (.whenComplete cf
             (reify BiConsumer
               (accept [_ r e]
                 (if (nil? e)
                   (s r) (f e)))))
           #(.cancel cf true))
         (catch Throwable e
           (f e) #(do)))))

(defmacro from-cf [& body]
  `(from-cf-call (fn [] ~@body)))

👍 1
leonoel 2025-02-27T18:08:01.794139Z

The exact adapter logic may vary depending on the semantics of your future, especially how it behaves on cancellation