Cuando se escribe:
(def foo "a")
(def bar "b")
(def zip "c")
que haya definido tres símbolos: foo
, bar
zip
y asociados con los valores: "a"
, "b"
y "c"
.
La asociación se almacena dentro de la tabla namsepace, por lo que si el uso de la réplica, el espacio de nombres sería user
por defecto, por lo que la tabla de espacio de nombres de usuario podría contener ahora:
{foo
#'user/foo
bar
#'user/bar,
zip
#'user/zip}
se puede ver la tabla de espacio de nombres haciendo: (ns-interns *ns*)
Ahora bien, si escribe: (foo bar zip)
dentro de Clojure, el lector podrá hacerlo de cuatro formas diferentes. Deberá especificar al lector de qué manera debe leerse. Ahí es donde entran en juego `
, '
y list
.
Caso de ningún indicador:
(foo bar zip)
Cuando simplemente por escrito sin ningún indicador, el lector interpretará esto como una S-expresión y la interpretará foo
como una correlación de símbolos a una función, con bar
y zip
como asignación de símbolos a los valores que se pasarán a la función foo
.
En nuestro caso, se producirá una excepción:
java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IFn
Esto es porque no se definió una función foo
, foo
se asoció con "a"
, que es una cadena, no un polipéptido IFN (una función Clojure).
Si se define la función foo
, habría llamado foo
pasando como argumento "b"
y "c"
.
Caso de list
:
(list foo bar zip)
Cuando se utiliza el símbolo de la lista, el lector es en realidad interpretando esta la misma manera que el caso no es indicativa. Es decir, está buscando un símbolo list
que se asigna a una función que tomará los valores asociados mapeados a foo
, bar
y zip
como argumentos. La función list
está predefinida por Clojure dentro del espacio de nombres clojure.core; devuelve una lista de sus argumentos.
Así que cuando el lector busca list
, se encuentra la función clojure.core, entonces busca el símbolo foo
, y encuentra que se asigna a "a"
, y así sucesivamente. Una vez que ha encontrado toda la asignación para los símbolos, llama al list
y le pasa los valores asociados de foo bar zip
, que serían "a" "b" "c"
. Entonces (list foo bar zip)
es lo mismo que (list "a" "b" "c")
.
Caso de '
:
'(foo bar zip)
La cita '
le dice al lector que la forma que sigue debe ser leída como es. En nuestro caso, foo
, bar
y zip
son símbolos, y (foo bar zip)
es una lista de símbolos. Entonces el lector interpretará esto como una lista de símbolos.
Es por eso que cuando ejecuta (apply str '(foo bar zip))
va a llamar al str 'foo 'bar 'zip
que le dará foobarzip
. Es decir, convertirá cada símbolo en la lista de símbolos a una representación de Cadena, y luego los concatenará en una Cadena.
Tomando el formulario como está, pasa como argumento una lista de símbolos, sin evaluar los símbolos, es decir, sin buscar con qué están asociados. Si ejecutó (eval '(foo bar zip))
, pasará una lista de símbolos al eval
, y eval
evaluará los símbolos a valores y devolverá una lista de los valores a los que se asignan los símbolos. Entonces, puede pensar en la cita '
como pasar el código como código.
Caso de `
:
`(foo bar zip)
Ésta es un poco más complicado. El lector verá la comilla inversa `
y resolverá los símbolos dentro de la lista de símbolos recursivamente para obtener una lista de símbolos totalmente calificados.
Básicamente, cuando el lector busca símbolos dentro de la tabla de símbolos, lo hace desde la tabla de símbolos del espacio de nombres actual. Un símbolo completamente calificado, es un símbolo que incluye la información del espacio de nombres. Por lo tanto, al ejecutar `(foo bar zip)
, el lector reemplazará esos símbolos con los completamente calificados, convirtiéndolo en (user.foo user.bar user.zip)
.
Es posible decirle al lector que evalúe algunos de los elementos en la lista, mientras cambia otros a símbolos totalmente calificados. Para ello, el prefijo de los símbolos que desea evaluados con ~
como en:
`(foo ~bar zip)
le dará
(clojure.foo "b" clojure.zip)
Efectivamente, la comilla inversa `
es mucho más similar a la cita '
en que lo hace no evalúa, sino que simplemente devuelve el código, excepto que manipula el código para que sea devuelto un poco por los símbolos totalmente calificables dentro de él. Esto tiene implicaciones para las macros, donde a veces es posible que desee una referencia totalmente calificada, para buscar desde otro espacio de nombres, y algunas veces desea flexibilidad al decir, busque este símbolo en el espacio de nombres actual.
No hay ninguna abreviatura para una lista porque una lista es de importancia secundaria para Clojure. –