Clojure: разрешение объявляет символ - PullRequest
7 голосов
/ 14 января 2012

Я получаю странное поведение, когда проверяю, можно ли разрешить символ.

user=> ok
CompilerException java.lang.RuntimeException: Unable to resolve symbol: ok in this context, compiling:(NO_SOURCE_PATH:0)
user=> (resolve 'ok)
nil
user=> (if (resolve 'ok) "bla" (def ok 'ok))
"bla"
user=> ok
#<Unbound Unbound: #'user/ok>
user=> (def ok 'ok)
#'user/ok
user=> ok
ok

Может кто-нибудь сказать мне, откуда это может быть?Это поведение предназначено?

Ответы [ 2 ]

4 голосов
/ 15 января 2012

(def ok "whatever") создает переменную с именем ok во время компиляции . Компилятор просматривает всю форму, чтобы скомпилировать ее, обнаруживает, что вы определите переменную с именем ok, и создает ее для вас (без привязки), прежде чем ваша форма будет фактически выполнена. Когда форма def действительно выполняется, значение времени выполнения выражения будет присвоено переменной user/ok. В вашем примере этого не происходит, потому что var уже создан, а ветвь if идет другим путем.

Использование bound? в качестве замены является ужасной идеей, поскольку она проверяет нечто совершенно иное: имеет ли указанная переменная var (которая должна существовать) привязку, либо постоянную, либо локальную для потока.

1 голос
/ 16 января 2012

Поскольку я использую его только внутри макроса, теперь я использую его следующим образом

(defmacro bla [x]
    (if (resolve x) x `(def ~x '~x)))

И теперь он работает, поскольку def находится внутри формы в кавычках и оценивается после разрешения.

...