Estoy aprendiendo acerca de las macros de Clojure, y los ejemplos de código a veces tendrán los constructos '~symbol
o alternativamente ~'symbol
. Sé que (quote
y '
impiden que se evalúe un formulario, y que la comilla inversa agrega adicionalmente la calificación del espacio de nombres, y que ~ hace que se evalúe un formulario citado. Mi pregunta es: ¿por qué es útil detenerse y luego comenzar la evaluación? También asumo que ~'symbol
y '~symbol
son diferentes, pero ¿cómo?¿Cuál es el propósito de ~ 'o' ~ en Clojure?
Respuesta
~'symbol
se utiliza para producir un sin calificar símbolo. Las macros de Clojure capturan el espacio de nombre de forma predeterminada, por lo que un símbolo en una macro normalmente se resolvería en (your-namespace/symbol)
. La expresión unquote-quote da como resultado directamente el nombre del símbolo simple, no calificado - (symbol)
- mediante la evaluación de un símbolo entre comillas. De la alegría de Clojure:
(defmacro awhen [expr & body]
`(let [~'it ~expr] ; refer to the expression as "it" inside the body
(when ~'it
(do [email protected]))))
(awhen [:a :b :c] (second it)) ; :b
'~symbol
es probable utiliza para insertar un nombre de la macro o algo similar. Aquí, symbol
estará vinculado a un valor - let [symbol 'my-symbol]
. Este valor se inserta en el código que produce la macro evaluando symbol
.
(defmacro def-symbol-print [sym]
`(defn ~(symbol (str "print-" sym)) []
(println '~sym))) ; print the symbol name passed to the macro
(def-symbol-print foo)
(print-foo) ; foo
~
es un lector de macros para la función unquote
. dentro de una lista citado provoca un símbolo que va a evaluarse en lugar de utilizar como un símbolo literal
user> (def unquoted 4)
user>`(this is an ~unquoted list)
(user/this user/is user/an 4 clojure.core/list)
user>
todo excepto el símbolo no cotizados se utilizó simplemente como un símbolo donde no indicada se resolvió a su valor de 4. Este es más a menudo se usa para escribir macros. La réplica también imprime el espacio de nombre (usuario) delante de los nombres cuando está imprimiendo la lista resultante.
muchas macros, son básicamente solo plantillas diseñadas para hacer un montón de pequeñas variaciones en algo que no se puede hacer en una función. En este ejemplo artificial, una macro de plantilla define una función produciendo una llamada a def. sintaxis de la cotización con unquoting hace esto mucho más fácil de leer:
user> (defmacro def-map-reducer [name mapper reducer]
`(defn ~name [& args#]
(reduce ~reducer (map ~mapper args#))))
#'user/def-map-reducer
user> (def-map-reducer add-incs inc +)
#'user/add-incs
user> (add-incs 1 2 3 4 5)
20
en comparación con:
user> (defmacro def-map-reducer [name mapper reducer]
(let [args-name (gensym)]
(list `defn name [`& args-name]
(list `reduce reducer (list `map mapper args-name)))))
#'user/def-map-reducer
user> (def-map-reducer add-decs dec +)
#'user/add-decs
user> (add-decs 1 2 3 4 5)
10
user>
en el segundo ejemplo también no utilizar la función de auto-gensyms porque no soy de una sintaxis-cita
Así que sé por qué querría usar ~ delante de un símbolo en una lista que había citado previamente, mi pregunta es específicamente por qué usaría ~ 'o' ~ uno al lado del otro. – Alex
espero que este ejemplo muestre la motivación mejor, gracias por los comentarios :) –
- 1. ¿Cuál es el propósito de CXF o Spring WS
- 2. ¿Cuál es el propósito de :: en C#?
- 3. ¿Cuál es el propósito de Rake?
- 4. ¿Cuál es el propósito de precompiledApp.config?
- 5. ¿Cuál es el propósito de config.assets.precompile?
- 6. ¿Cuál es el propósito de 'Class.forName ("MY_JDBC_DRIVER")'?
- 7. WPF: ¿Cuál es el propósito de App.xaml?
- 8. ¿Cuál es el propósito de 'var'?
- 9. ¿Cuál es el propósito de `qt_noop`
- 10. ¿Cuál es el propósito de String.IsInterned?
- 11. ¿Cuál es el propósito de Function.const?
- 12. ¿Cuál es el propósito de layout.xml?
- 13. ¿Cuál es el propósito de requestWindowFeature()?
- 14. ¿Cuál es el propósito de IntentSender?
- 15. ¿Cuál es el propósito de utilizar NSOrderedSame?
- 16. ¿Cuál es el propósito de Mage_Core_Block_Template_Facade
- 17. ¿Cuál es el propósito de Membership.ValidateUser()
- 18. ¿Cuál es el propósito de Anorm's Pk?
- 19. ¿Cuál es el propósito de Active Records?
- 20. ¿Cuál es el propósito de 'n = n'?
- 21. ¿Cuál es el propósito del pase indefinido?
- 22. ¿cuál es el propósito de glClear (GL_DEPTH_BUFFER_BIT)
- 23. ¿Cuál es el propósito de git-mv?
- 24. ¿Cuál es el propósito de __cxa_pure_virtual?
- 25. ¿Cuál es el propósito de JNDI
- 26. ¿Cuál es el propósito de Ext.require
- 27. ¿Cuál es el propósito de Array.GetLowerBound (int)?
- 28. ¿cuál es el propósito de Thread.holdsLock (lock)?
- 29. ¿Cuál es el propósito del control VisitorIdentification?
- 30. ¿Cuál es el propósito de glNormal3f en OpenGL ES?
:) Gracias, eso tiene sentido. – Alex
todavía hay un punto que no me queda claro: '(unquote (quote user/foo))' da como resultado 'foo' en lugar de' user/foo', ¿cuándo y cómo ocurre que el espacio de nombres se elimina? ¿Cómo es consistente con el comportamiento "normal" de 'unquote' que evalúa la siguiente forma? – skuro
El primer ejemplo no funciona. Debería ser '\' (let [~ 'it ~ expr] ... ' – Ming