This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-04-25
Channels
- # aleph (6)
- # beginners (6)
- # boot (94)
- # cider (34)
- # cljs-dev (36)
- # cljsrn (12)
- # clojure (124)
- # clojure-dev (41)
- # clojure-dusseldorf (6)
- # clojure-italy (3)
- # clojure-norway (1)
- # clojure-russia (161)
- # clojure-sg (7)
- # clojure-spec (71)
- # clojure-uk (95)
- # clojurescript (38)
- # core-async (16)
- # cursive (14)
- # data-science (1)
- # datascript (12)
- # datomic (15)
- # emacs (22)
- # funcool (2)
- # hoplon (15)
- # jobs-rus (2)
- # juxt (9)
- # liberator (7)
- # lumo (1)
- # off-topic (136)
- # onyx (24)
- # pedestal (39)
- # perun (2)
- # planck (20)
- # re-frame (23)
- # spacemacs (31)
- # unrepl (5)
- # untangled (1)
- # vim (1)
- # yada (29)
A question related to multimethods
Why there is not add-method
while there is remove-method
?
defmethod?
why is the empty let
needed to get push-thread-bindings
working? https://github.com/clojure/clojure/blob/clojure-1.9.0-alpha14/src/clj/clojure/core.clj#L1956
hmmm, not following
why does that matter for this case?
I noticed this initially at the repl
user=> (def ^:dynamic *foo* 1)
#'user/*foo*
user=> (push-thread-bindings {#'*foo* 2})
nil
user=> *foo*
1
@alexmiller Is it ok to call defmethod
at run time (e.g. in a handler function)?
I mean is this code considered clean code or not?
(defmulti foo (fn [x] x) )
(defn bar []
(defmethod foo :a [x] :a))
To me it looks weird to have defmethod
inside defn
!?!?!
@nathanmarz to be more explicit: both compile
and eval
push some thread bindings before evaluationg the expression and then pop them after evaluation finishes -- what's happening is the following:
- push-thread-binding from the compiler
- push-thread-binding from the user code
- pop-thread-binding from the compiler
so the user code thread-binding gets popped and the compiler thread-binding stays on the thread local frame stack
oh I see
the difference between (let [] (push-thread-binding ..) ..)
and (do (push-thread-binding ..) ..)
is that the former is executed as a single expression so it's evaluated before the compiler pops its bindings while the latter is executed as multiple expressions and the compiler interferes
this means that you can never push thread bindings in a top level form, and as a side-effect of the fix for the gilardi scenario, never from a top-level do
either
cool, thanks for the explanation
Reasking the question because previously it was in the middle of another thread
@alexmiller Is it ok to call defmethod
at run time (e.g. in a handler function)?
(defmulti foo (fn [x] x) )
(defn bar []
(defmethod foo :a [x] :a))
@viebel defmethod
doesn't actually def a var, so using defmethod
inside a defn
is safe
@viebel you can also call .addMethod
directly on the multimethod if you wanted, just like defmethod
does: https://github.com/clojure/clojure/blob/clojure-1.9.0-alpha14/src/clj/clojure/core.clj#L1773-L1777
But then it won’t be portable - as in cljs, we have -add-method
https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/core.cljc#L2612
yep, so a defmethod
inside a defn
is the portable solution
the issue with using defmethod
like that is that you can't parametrize the dispatch value
@bronsa I don't think that's correct. I've parameterized the dispatch value before
well to be fair, most macros don't work that way, but in this case it does.
@tbaldridge you allude that calling defn
inside defn
is not safe?
user=> x
CompilerException java.lang.RuntimeException: Unable to resolve symbol: x in this context, compiling:(NO_SOURCE_PATH:0:0)
user=> (defn y [] (defn x []))
#'user/y
user=> x
#object[clojure.lang.Var$Unbound 0x573fd745 "Unbound: #'user/x"]
What does it mean?
I would guess that it means x isn’t defined until y is invoked because before that the x definition hasn’t run.
The problem is x
is created when the defn
is compiled, but it isn't bound until y
is called.