online - clojurescript
¿Cómo funciona la cita de sintaxis de clojure? (3)
No creo que haya una sintaxis-cita equivalente a la función de quote
.
El lector Clojure está (actualmente) escrito en Java. La clase SyntaxQuoteReader
en src/jvm/clojure/lang/LispReader.java
en la fuente de Clojure es probablemente lo que querrá leer. Parece bastante complejo. Puedes verlo creando listas como (seq (concat ...))
allí.
ret = RT.list(SEQ, RT.cons(CONCAT, sqExpandList(seq)));
Es común que el lector no devuelva el código directo de Clojure, sino que haga lo correcto en Java-land inmediatamente. Por ejemplo, ''[1 2 3]
no produce el código Clojure (vector 1 2 3)
. Tal vez podría funcionar de alguna manera, pero no funciona. El lector simplemente crea y devuelve el objeto vectorial en sí.
Del mismo modo, SyntaxQuoteReader
hace algo de magia en Java de inmediato para resolver los espacios de nombres de los símbolos y crear los propios gensyms y devuelve un código de Clojure dañado y de aspecto complicado que hace lo correcto, pero no es necesariamente fácil de leer para un humano. Si es así porque tiene que ser, o porque es más fácil hacerlo de esta manera en Java, o por rendimiento o por alguna otra razón, no lo sé. Del mismo modo, no sé si quasiquote
podría existir como una macro simple / forma especial en Clojure y no, o si no podría existir en absoluto. Aunque no veo por qué no podría.
WrappingReader
en el mismo archivo es la clase que maneja ''
( quote
antigua simple). Puede ver que simplemente envuelve lo que se le pasa en una lista que contiene la quote
del símbolo más su argumento. Es mucho más simple. Tenga en cuenta que esta clase también maneja @
, para que ''@foo
regrese (deref foo)
.
Este hilo podría arrojar algo más de luz.
Editar
Aquí hay una macro de quasiquote
prueba de concepto. Tenga en cuenta que este código confía y abusa de los elementos internos de Clojure de una manera horrible. Por favor, no uses esto para nada.
user> (defmacro quasiquote [x]
(let [m (.getDeclaredMethod clojure.lang.LispReader$SyntaxQuoteReader
"syntaxQuote"
(into-array [Object]))]
(.setAccessible m true)
(.invoke m nil (into-array [x]))))
#''user/quasiquote
user> (let [x 123] `(x ''x ~x))
(user/x (quote user/x) 123)
user> (let [x 123] (quasiquote (x ''x ~x)))
(user/x (quote user/x) 123)
Varios caracteres especiales en clojure son abreviaturas de cosas
(quote (ab))
es lo mismo que ''(ab)
Como puedes ver evaluando:
user> ''''(a b)
(quote (a b))
Esto parece ser una sintaxis como abreviatura, lo que me parece una buena idea.
Pero la sintaxis-cita, `parece especial. No puedo pensar lo que sería equivalente a
`(a b)
Habría adivinado algo así como (syntax-quote (ab))
, pero no funciona, y si he adivinado mal, no puedo descubrir cómo se llama realmente.
user> ''`(a b)
(clojure.core/seq (clojure.core/concat (clojure.core/list (quote user/a)) (clojure.core/list (quote user/b))))
Es un poco desconcertante.
¿Presumiblemente el lector está haciendo algo especial, tal vez porque necesita saber los espacios de nombres?
Curiosamente, la sintaxis especial utilizada en la sintaxis-cita funciona como esperaba:
user> ''~a
(clojure.core/unquote a)
user> ''~@a
(clojure.core/unquote-splicing a)
user> ''~''a
(clojure.core/unquote (quote a))
a excepción de éste:
user> ''a#
a#
Lo que habría pensado producir algo como (unquote (gensym "a"))
Me doy cuenta de que estoy siendo un poco débil aquí, y debería ir y leer el código. Si a nadie le apetece explicar qué está pasando o dar una referencia, ¿puede alguien darme una pista sobre cómo encontrar el código relevante y qué buscar?
Parece que tienes un gran conocimiento de la sintaxis de la macro para empezar, así que no hay mucho que pueda agregar.
Hay un poco de cobertura en los foros de programación de clojure . y puede leer el código aquí en la línea 352
hiredman ha implementado una versión completa de syntax-quote basada en clojure. No para los débiles de corazón, sino una buena prueba de concepto.