Привязать условно динамический var из ядра Clojure для обратной совместимости - PullRequest
0 голосов
/ 24 октября 2018

Я некоторое время пытался решить этот nREPL билет , и у меня нет идей, поэтому я решил попросить немного помощи здесь.

В основном мынужно связывать *print-namespace-maps* только в том случае, если он присутствует, или найти способ определить, не присутствует ли он, что не испортит Clojure 1.9+.

Вот некоторые вещи, которые не работают:

;; compilation error
(when (resolve '*print-namespace-maps*)
  (set! *print-namespace-maps* (@bindings #'*print-namespace-maps*)))

;; shadows `clojure.core/*print-namespace-maps*` on 1.9, as the def gets executed always
(when-not (resolve 'clojure.core/*print-namespace-maps*)
  (def ^:dynamic *print-namespace-maps*
    "Define the var for clojure versions below 1.9"
    nil))

Кажется, что динамические переменные вообще не могут быть условно связаны, что на самом деле отстой, но я думаю, что должно бытькакой-то способ сделать что-то вроде того, к чему мы стремимся.

Посмотрите на связанную проблему для получения более подробной информации.Любая помощь будет высоко ценится!

1 Ответ

0 голосов
/ 24 октября 2018

Я не до конца понимаю детали связанной проблемы или подразумеваемого 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...