Я не до конца понимаю детали связанной проблемы или подразумеваемого nREPL, но поведение def
немного удивляет:
Clojure 1.8.0
user=> (when false (def ^:dynamic *foo* 1))
nil
Я бы ожидал, что не будет*foo*
var после этой оценки, но она создает несвязанную переменную:
user=> (var-get #'*foo*)
#object[clojure.lang.Var$Unbound 0x20da8800 "Unbound: #'user/*foo*"]
И я полагаю, что поведение компилятора def
является причиной исключения в 1.9 в вашем примере:
WARNING: *print-namespace-maps* already refers to: #'clojure.core/*print-namespace-maps* in namespace: user, being replaced by: #'user/*print-namespace-maps*
Возможно, макрос можно использовать так, чтобы проверка resolve
происходила во время раскрытия макроса и не генерировала def
, если он разрешается:
(defmacro def-dynamic-when-not-resolve [sym value]
(when-not (resolve sym)
`(def ~(vary-meta sym assoc :dynamic true) ~value)))
Кажется, он работает на Clojure 1.8:
Clojure 1.8.0
user=> (def-dynamic-when-not-resolve *print-namespace-maps* 'sure)
#'user/*print-namespace-maps*
user=> *print-namespace-maps*
sure
и на Clojure 1.9:
Clojure 1.9.0
user=> (def-dynamic-when-not-resolve *print-namespace-maps* 'sure)
nil
user=> *print-namespace-maps*
true