clj-commons / potemkin

some ideas which are almost good
572 stars 53 forks source link

Macros define var even if not evaluated #41

Closed marick closed 8 years ago

marick commented 9 years ago

Midje wants to conditionally import certain vars when running in the repl. I discovered that the vars are created even when not running in the repl. Potemkin inherits this (mis)behavior from def:

user=> (if false (do (def derp3 3)))
nil
user=> ( (ns-publics *ns*) 'derp3)
#'user/derp3
user=> (deref #'derp3)
#object[clojure.lang.Var$Unbound 0x745c8706 "Unbound: #'user/derp3"]

Because of this, Potemkin's behavior is arguably correct.

Here's a simplified example of the Midje case:

user=> ( (ns-publics *ns*) 'load-config-files)
nil
user=> (if false (potemkin.namespaces/import-vars [midje.config load-config-files]))
nil
user=> ( (ns-publics *ns*) 'load-config-files)
#'user/load-config-files

;;; This is not a copy of the var. For example, the metadata is wrong:

user=> (meta ( (ns-publics *ns*) 'load-config-files))
{:ns #object[clojure.lang.Namespace 0x4d1f34a6 "user"], :name load-config-files}
user=> (meta #'midje.config/load-config-files)
{:arglists ([]), :line 131, :column 1, :file "midje/config.clj", :name load-config-files, :ns #object[clojure.lang.Namespace 0x58378d16 "midje.config"]}

;;; ... and there's no value.
user=> (deref ( (ns-publics *ns*) 'load-config-files))
#object[clojure.lang.Var$Unbound 0x94a34ff "Unbound: #'user/load-config-files"]
ztellman commented 8 years ago

This wasn't intentional, but I think it's enough of an "expected" behavior that I'm going to leave this as-is. Thanks for the report!