This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-03-27
Channels
- # bangalore-clj (1)
- # beginners (27)
- # boot (16)
- # cider (14)
- # cljs-dev (94)
- # cljsrn (8)
- # clojure (229)
- # clojure-dev (5)
- # clojure-dusseldorf (6)
- # clojure-italy (8)
- # clojure-norway (8)
- # clojure-russia (22)
- # clojure-sanfrancisco (2)
- # clojure-spec (48)
- # clojure-uk (44)
- # clojurescript (47)
- # core-async (87)
- # cursive (43)
- # datascript (22)
- # datomic (20)
- # defnpodcast (5)
- # emacs (6)
- # hoplon (4)
- # jobs-rus (4)
- # keechma (2)
- # klipse (8)
- # leiningen (2)
- # luminus (2)
- # lumo (14)
- # om (38)
- # onyx (4)
- # overtone (3)
- # pedestal (41)
- # planck (72)
- # powderkeg (42)
- # proton (46)
- # protorepl (9)
- # reagent (9)
- # ring (47)
- # ring-swagger (5)
- # rum (7)
- # sql (22)
- # unrepl (1)
- # untangled (24)
- # vim (19)
- # yada (5)
Issue #27 is killing me: how can we have not seen it sooner? (okay we are used to cycling the sparkcontext when things get weird)
The core of the issue os that (defn foo …)
creates a class named ns$foo
and when you redefine it you get another class going by the same name. Once packaged and sent to workers, workers have two copies of the class and use the first one (the older one).
so if you have severak redefs between two barriers only the last one is put in the jar
scala is not as repl centric as clojure, from what I remember, app in the repl is a bit foreign (keeping state not so straightforward)
some options: • automatically cycle context on redefs 😞 • or document cycling cases (along with protocol redefs) • rename classes (either at broadcast time or by hotpatching clojure)
because, before putting classes into the jar you have to transform the class to change its name and change all callers too to refer to the new name and...
it’s not even going to work because at the other end we can’t change kry ClassResolver.
this test should always be true https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Compiler.java#L3932
first thought that since this is related to loading classes, I’d look into DynamicClassloader, but now that I did so, it seems to be more of a cache compiled classes, for which the name munging has to be done first
user=> (eval '(do (defn x [] 1) (def x1 x) (defn x [] 2) (def x2 x) [x1 x2]))
[#object[user$x 0xbe35cd9 "user$x@be35cd9"] #object[user$x 0x44821a96 "user$x@44821a96"]]
user=> (map #(%) *1)
(1 2)
user=> (map class *2)
(user$x user$x)
user=> (map #(.getClassLoader %) *1)
(#object[clojure.lang.DynamicClassLoader 0x72cde7cc "clojure.lang.DynamicClassLoader@72cde7cc"] #object[clojure.lang.DynamicClassLoader 0x696da30b "clojure.lang.DynamicClassLoader@696da30b"])
user=> (map #(.getParent %) *1)
(#object[clojure.lang.DynamicClassLoader 0x2accdbb5 "clojure.lang.DynamicClassLoader@2accdbb5"] #object[clojure.lang.DynamicClassLoader 0x2accdbb5 "clojure.lang.DynamicClassLoader@2accdbb5"])
so despite classes having same name they have different classloaders (which share common ancestor)
Looks like a step forward
user=> (class foo)
user$foo__1596
user=> (defn foo [])
#'user/foo
user=> (class foo)
user$foo__1601
so normally when one does defn foo
in ns1
, then uses ns1/foo
in ns2/bar
, in order to make ns2/bar
use re-defined ns1/foo
, one has to redefine ns2/bar
, if I’m correct