@dominicm on why I consider bound-fn
unfit?
@cgrand mmhm, and what you think more suitable.
JS being single threaded doesnβt mean you canβt have several logical processes (cooperatively) sharing the thread. In many cases the callback you pass is the continuation of the current process. On the JVM this style is infrequent because there are preemptive threads. So bound-fn
is ok for the occasional call. In js you wouljd litter your code with bound-fn
calls.
Furthermore bound-fn
flattens the dynamic bindings stack. Which makes impossible some continuation stuff. E.g. in Clojure (with-open [f ...] (do sync IO))
canβt be translated to (with-open [f ..] (.on f "data" (bound-fn ...)))
because resource reclamation must happen in the continuation (otherwise by the time the callback is called the resource is already disposed.
Basically I think the callback-as-continuation scenario needs special support for dynamic variables and for the other dynamically scoped feature: try/catch/finally
I see, interesting. A difficult thing to achieve though! Although very simple if we were to generate ES.next code (with the new async functions)
could you explain how that would help @dominicm ?
@pesterhazy my understanding is that try/catch works with e.g. async/await
That might be wrong though now I think about it
https://pouchdb.com/2015/03/05/taming-the-async-beast-with-es7.html yes, yes you can
Isn't the continuation approach exactly what cljs-zones
does?
I might have misread it from the Klipse example above
https://github.com/binaryage/cljs-zones/blob/master/readme.md#faq
Reading as we speak π
I wouldn't say exactly. Plus I believe the prototype-based implementation is flawed: a set on a dynamic var bound in an outer scope should survive to the current scope
@richiardiandrea (binding [a 1] (binding [b 2] (set! a 3)) a)
should evaluate to 3 not to 1.
returns 3
no sorry π
(ns zones.test
(:require [zones.core :as zones :include-macros true]))
(zones/binding [a 1] (zones/binding [b 2] (set! a 3)) a)
this evaluates to 3
again, not the author here, but prototypes inherit properties so this can go as deep as needed...
there are also a bunch of tests: https://github.com/binaryage/cljs-zones/blob/master/test/src/tests/zones/tests/core.cljs#L97
And if you replace set!
by zone/set! And plain a by (zone/get a) β sorry to use you as a repl but I only have two thumbs
np let me check π
(ns zones.test
(:require [zones.core :as zones :include-macros true]))
(zones/binding [a 1] (zones/binding [b 2] (zones/set! a 3)) (zones/get a))
=> 3no
zones/get
is the same
(ns zones.test
(:require [zones.core :as zones :include-macros true]))
(zones/binding [a 1] (zones/binding [b 2] (zones/set! a 3)) a)
...this one does not work as expected actually... so you need a zones/get
I like, it is good to see if we can break it π
Hmm I'll have to look at the impl because the prototype chain only works for getting a property. All sets are shallow.
Found: https://github.com/binaryage/cljs-zones/blob/master/src/lib/zones/core.cljs#L11-L20
So the protochain is explicitly walked. Would be interesting to benchmark as this kind of behavior used to trigger perf penalties (because of cache invalidation).