Можно ли предопределённая динамика неявно завернутым в обязательной форме пути выполнения? Потому что это работает, например:
user=> (def ^:dynamic *x*)
user=> (binding [*x* false] (set! *x* true))
true
user=>
Единственное, что следует отметить, что в документации прямо говорит, что его ошибка, чтобы попытаться изменить корень связывания через set!
см:
http://clojure.org/reference/vars
Это также возможно, что встроенные функции рассматриваются в исключительных случаях, например, если вы посмотрите на метаданные х:
user=> (meta #'*x*)
{:dynamic true, :line 1, :column 1, :file "/private/var/folders/8j/ckhdsww161xdwy3cfddjd01d25k_1q/T/form-init5379741350621280680.clj", :name *x*, :ns #object[clojure.lang.Namespace 0x6b8f00 "user"]}
Он отмечен как динамичные, в то время как *warn-on-reflection*
не помечен как динамический, но до сих пор работает в обязательной форме:
user=> (meta #'*warn-on-reflection*)
{:added "1.0", :ns #object[clojure.lang.Namespace 0x377fc927 "clojure.core"], :name *warn-on-reflection*, :doc "When set to true, the compiler will emit warnings when reflection is\n needed to resolve Java method calls or field accesses.\n\n Defaults to false."}
user=> (binding [*warn-on-reflection* true] (set! *warn-on-reflection* false))
false
user=>
Предположительно это для обратной совместимости, так как в более ранних версиях Clojure вары с наушниками (звездами в каждой стороне) были по соглашению. Но в любом случае это просто показывает, что встроенные элементы обрабатываются несколько иначе.
Теперь я решил взять это немного дальше, и grep
исходный код Clojure, ищет warn-on-reflection
, что приводит меня к постоянному WARN_ON_REFLECTION
, что приводит меня к строкам кода, как это в RT.java
:
https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/RT.java#L467
Var.pushThreadBindings(
RT.mapUniqueKeys(CURRENT_NS, CURRENT_NS.deref(),
WARN_ON_REFLECTION, WARN_ON_REFLECTION.deref()
,RT.UNCHECKED_MATH, RT.UNCHECKED_MATH.deref()));
что приводит меня к мысли, что мое первоначальное предположение было верным, что некоторые специальные глобальные вары неявно обернуты в потоке локального связывания.
EDIT:
Как уже упоминалось в комментариях, вы можете использовать clojure.core/push-thread-bindings
, но обязательно следовать советам документации и завернуть в Try/улов /, наконец, pop-thread-bindings
в конце концов блока. И в этот момент вы бы только что внедрили binding
(например, запустите (source binding)
в repl), что, вероятно, почему документ явно предупреждает, что push-thread-bindings
является низкоуровневой функцией, а binding
предпочтительнее.
Теперь я вижу, спасибо! Также [вот почему] (https://github.com/clojure/clojure/blob/d920ada9fab7e9b8342d28d8295a600a814c1d8a/src/jvm/clojure/lang/RT.java#L228) Я не смог найти определение '* warn-on- отражение * 'в' clojure.core'. – OlegTheCat
Возможно, вы захотите добавить, что вы, возможно, можете сделать свою собственную динамическую переменную одинаковой с https://clojuredocs.org/clojure.core/push-thread-bindings. – coredump