leonoel / cloroutine

Coroutine support for clojure
Eclipse Public License 2.0
230 stars 10 forks source link

differences with clj-conduit #2

Closed zcaudate closed 5 years ago

zcaudate commented 5 years ago

I noticed that there is a doc on implementing clj-conduit's await and yield.

What are the advantages of cloroutine over clj-conduit?

leonoel commented 5 years ago

It's somehow an apples-and-oranges question, because cloroutine is a low-level tool aiming to ease the development of higher level constructs such as clj-conduit.

The guide is a POC showing how it can be achieved. This is not a library, its purpose is purely didactic and I have not tested it in the wild nor performed any perf-related work. If you're interested using it in production you should look at clj-conduit, AFAIK it is iso-feature with the guide.

clj-conduit currently uses another implementation based on core.async, which has several limitations (see the implementation section of my design notes for details). If you encounter one of those, you could suggest clj-conduit's maintainer to switch its implementation to cloroutine.

zcaudate commented 5 years ago

That makes sense. I have reservations about making everything look like a channel and so am looking at alternatives.

This might not be related but how would cloroutine provide a better syntax working with promises, ie:

(-> (js/fetch <URL>
              (js-obj "method" "POST"
                      "body"  body))
    (.then (fn [res]
             (if (= (.-status res) 200)
               (.text res)
               (js/Promise.reject (js/Error "Network call failed")))))
    (.then (fn [text] (js/console.log text))))
leonoel commented 5 years ago

Providing a better syntax to work with asynchronous promises is pretty much the value proposition of async/await. Your example would look like this :

(async
  (let [res (await (js/fetch <URL>
                             (js-obj "method" "POST"
                                     "body"  body)))]
    (when-not (= (.-status res) 200)
      (throw (js/Error "Network call failed")))
    (js/console.log (.text res))))

which is arguably better.

This guide shows how to achieve this in JVM clojure. The approach can totally be ported to clojurescript (with native promises or any other implementation).

I'm not willing to include this feature in cloroutine (I want to keep it low-level) but the guide can serve as a basis for a third-party library. promesa has this feature as well (with some flaws, however), maybe hardening it would be a better option ?

zcaudate commented 5 years ago

Would it be possible to put the cljs version as a gist? I'd like to try it out but I'm not sure if I can come up with it myself.

I've looked at promesa and would prefer using the native promises. To me, I feel that there is a fundamental difference programming on the jvm vs the browser. There are more options available on the jvm to achieve concurrency. Whilst a unified interface might mean a library can work on both platforms, it adds dependency and sometimes unnecessary complexity - especially during interop with existing libraries.

leonoel commented 5 years ago

Here is one possibility

zcaudate commented 5 years ago

that's brilliant - and really concise. thank you.

niwinz commented 5 years ago

I have just noticed of this library (thanks to the mention), Very nice work, is really awesome. I'll try to take some time to experiment with this library and maybe in a future I can consider switch promesa impl from core.async to use cloroutine. I'll report any issue if found...

PD: I have just fixed the mentioned issue. PD2: @zcaudate promesa will be switch from bluebird to native promises on the next version (removing the bluebird dependency)

zcaudate commented 5 years ago

@niwinz brilliant. looking forward to it.