Thanks Justin, Sadly in my case those mutable container will not work because I was making a monkey-patch to a bug in a macro from other package.
Despite what I was doing, I think "a bad design" in clojure spec is too weak to fit this situation. If someone tells me "it is a bad design" I would think I will spend more development/computation time to make it work but I would still expect *correct* result. "An undefined behavior" would be a more suitable. On Thursday, June 29, 2017 at 1:15:23 PM UTC-7, Justin Smith wrote: > > Clojure's compiler (there's no interpreter) creates vars for every def > inside a form it compiles. Before the def actually runs it's unbound (as if > you had used declare). > > Generally def and defn that are not top level forms are signs of a bad > design. If you need runtime rebinding use a proper mutable container like > and atom, ref, or agent, this is what they are for, and they eliminate a > number of gotchas that come with runtime redefinition. > > On Thu, Jun 29, 2017 at 1:07 PM Kaiming Yang <yax...@gmail.com > <javascript:>> wrote: > >> Hi, >> Recently encountered a weird issue, A def in if clause declared a var but >> left it unbound. >> >> I encountered this issue when I was trying to implement something like >> "define a symbol if it is not defined yet". Naively I tried: >> >> (if (nil? (resolve 'foo)) >> (def foo 42)) >> ; Cannot use (def foo (if (nil? (resolve 'foo)) foo 42)) because foo >> might be macro >> >> I tried in repl and the result really surprised me: >> >> user=> foo >> >> CompilerException java.lang.RuntimeException: Unable to resolve symbol: >> foo in this context, >> compiling:(/private/var/folders/1h/vhl8yb657mjf3pchm9cbc40m63f2d3/T/form-init8893781347079502941.clj:1:1062) >> user=> (if (nil? (resolve 'foo)) >> #_=> (do (def foo 42) (prn "true-branch")) >> #_=> (prn "false-branch")) >> "false-branch" >> nil >> user=> foo >> #object[clojure.lang.Var$Unbound 0x6dc69f03 "Unbound: #'user/foo"] >> >> Seems once clojure interpreter declares the variable before really >> evaluate the clause with def. >> >> Is this an expected behavior? Should I ever use def in if or fn? >> >> Thanks! >> Kaiming >> >> -- >> You received this message because you are subscribed to the Google >> Groups "Clojure" group. >> To post to this group, send email to clo...@googlegroups.com >> <javascript:> >> Note that posts from new members are moderated - please be patient with >> your first post. >> To unsubscribe from this group, send email to >> clojure+u...@googlegroups.com <javascript:> >> For more options, visit this group at >> http://groups.google.com/group/clojure?hl=en >> --- >> You received this message because you are subscribed to the Google Groups >> "Clojure" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to clojure+u...@googlegroups.com <javascript:>. >> For more options, visit https://groups.google.com/d/optout. >> > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.