Clojure: Resolve declara el símbolo
Pregunta
Tengo un comportamiento extraño al verificar si se puede resolver un símbolo.
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
¿Alguien puede decirme de dónde podría venir esto? ¿Se pretende este comportamiento?
Solución
(def ok "whatever")
crea una variable nombrada ok
en el momento de la compilación. El compilador escanea todo el formulario para compilarlo, descubre que definirá un var llamado ok
, y lo crea para usted (sin vinculación), antes de que su forma se ejecute realmente. Cuando el def
El formulario realmente se ejecuta, el valor de tiempo de ejecución de la expresión se asignará a la var user/ok
. En su ejemplo, esto nunca sucede, porque el var ya ha sido creado y el if
Branch va al otro lado.
Usando bound?
Como sustituto, es una idea terrible, ya que prueba algo bastante diferente: si el VAR nombrado (que debe existir) tiene un enlace, ya sea permanente o local.
Otros consejos
Ya que solo lo uso dentro de una macro, ahora lo uso de la siguiente manera
(defmacro bla [x]
(if (resolve x) x `(def ~x '~x)))
Y ahora funciona ya que DEF está dentro del formulario citado y evaluado después de la resolución.