This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-04-30
Channels
- # aleph (12)
- # beginners (23)
- # boot (12)
- # cider (40)
- # cljs-dev (8)
- # cljsrn (20)
- # clojars (1)
- # clojure (122)
- # clojure-canada (2)
- # clojure-dev (21)
- # clojure-gamedev (2)
- # clojure-italy (3)
- # clojure-nl (12)
- # clojure-norway (1)
- # clojure-sanfrancisco (3)
- # clojure-spec (59)
- # clojure-uk (114)
- # clojurescript (50)
- # clojurex (1)
- # cursive (2)
- # datascript (2)
- # datomic (26)
- # emacs (5)
- # fulcro (19)
- # garden (1)
- # hoplon (54)
- # leiningen (42)
- # luminus (14)
- # off-topic (24)
- # om (5)
- # onyx (7)
- # re-frame (2)
- # reagent (31)
- # reitit (3)
- # ring-swagger (39)
- # shadow-cljs (8)
- # sql (3)
- # tools-deps (13)
in this talk https://youtu.be/cPNkH-7PRTk?t=4663 RH made it pretty clear he didn't want dynamic bindings to propagate to child threads, anyone knows what made it change his mind ?
Maybe that it was done in a read-only
manner? Something that's a little interesting in the implementation of Vars is that if a binding is propagated to a child thread, the child thread cannot call set!
on that binding
(binding [foo 4]
(set! foo 3)
(future (set! foo 44)))
Results in "Can't set!: foo from non-binding thread"
Also conveyance of bindings is only done automatically for futures and agents. That video is pretty old, so I'm not sure how the timeline of all these features fits together.
That being said, I'm glad we have binding conveyance.
assignment restriction in child threads mitigates the problem but you can still screw it up with mutable objects
true, that's the case with mutable objects in general though, nothing stops you from doing (atom (List.))
yes, but one of the benefits of thread local state is precisely to use (performant) unsynchronized state safely
I mostly use them for storing global-esque state instead of returning multiple values from a function.
When I want to pass something into a function, but that function may need to update that value.
I understand how binding conveyance can be useful, but I can hardly understand how it can be a good default behavior
Oh, implicit binding conveyance is useful for things like print:
(with-out-str
@(future (println "test")))
That's the original use case for this I think. Back when binding conveyance was introduced (2010) it was fairly common to pass db connections and IO streams around in dynamic bindings.
those were the days
And without that, things would just randomly break when you put them inside pmap
or any other function that used futures.