Muchos ejemplos de macros parecen ser sobre la ocultación de lambdas, p. con-abrir-archivo en CL. Estoy buscando usos más exóticos de macros, particularmente en PLT Scheme. Me gustaría tener una idea de cuándo considerar usar una macro vs. usar funciones.¿Para qué has usado las macros de Scheme?
Respuesta
sólo utilizar macros de Scheme (define-syntax
) para cosas pequeñas como mejor sintaxis lambda:
(define-syntax [: x]
(syntax-case x()
([src-: e es ...]
(syntax-case (datum->syntax-object #'src-: '_)()
(_ #'(lambda (_) (e es ...)))))))
que le permite escribir
[:/_ 2] ; <-- much better than (lambda (x) (/ x 2))
Dan Friedman tiene una aplicación endiablada de OO usando macros : http://www.cs.indiana.edu/~dfried/ooo.pdf
Pero, sinceramente, todos los útiles macros que he definido d son robadas de Paul Graham's On Lisp y generalmente son más fáciles de escribir con defmacro
(define-macro
en PLT Scheme). Por ejemplo, aif
es bastante feo con define-syntax
.
(define-syntax (aif x)
(syntax-case x()
[(src-aif test then else)
(syntax-case (datum->syntax-object (syntax src-aif) '_)()
[_ (syntax (let ([_ test]) (if (and _ (not (null? _))) then else)))])]))
define-syntax
es extraño en que sólo es fácil de usar para las macros muy simples, en las que se alegran de la incapacidad para capturar las variables; y macro DSL muy complicadas, donde se alegra de la imposibilidad de capturar variables fácilmente. En el primer caso, usted desea escribir el código sin pensarlo, y en el segundo caso ha pensado lo suficiente sobre el DSL que está dispuesto a escribir parte del mismo en el lenguaje syntax-rules
/syntax-case
que no es Scheme para evitar errores desconcertantes.
Pero no uso macros en Scheme. Idiomatic Scheme es tan funcional que muchas veces solo quieres escribir un programa funcional y luego esconder algunas lambdas. Me subí al tren funcional y ahora creo que si tienes un lenguaje lento o una buena sintaxis para lambda, incluso eso no es necesario, por lo que las macros no son tan útiles en un estilo puramente funcional.
Así que recomendaría Practical Common Lisp y On Lisp. Si desea utilizar PLT Scheme, creo que la mayoría de sus macros defmacro
funcionarán con define-macro
. O simplemente usa Common Lisp.
Si usa un parámetro de sintaxis, 'aif' se vuelve mucho más limpio para definir (y hygenic!):' (Define-sintaxis-parámetro it #f) (define-sintaxis aif (sintaxis-analizador [(_ prueba y luego else) # '(let ([resultado de la prueba]) (sintaxis-parametrizar ([it (make-rename-transformer result)]) (si result luego else)))])) – Jack
Comenzaré a responder la última pregunta. Cuándo usar una macro en lugar de una función. Las macros hacen cosas que las funciones no pueden hacer, y las funciones hacen lo que las macros no pueden hacer, por lo que será difícil mezclarlas, pero profundicemos.
Utiliza funciones cuando quiere los argumentos evaluados y macros cuando quiere que los argumentos no sean evaluados. Eso no es muy útil, ¿verdad? Utiliza macros cuando quiere escribir algo de forma diferente, cuando ve un patrón y desea abstraer. Por ejemplo: defino tres funciones llamadas foo-create, foo-process y foo-destroy para diferentes valores de foo y con cuerpos similares donde el único cambio es foo. Hay un patrón pero un nivel demasiado alto para una función, por lo que crea una macro.
En mi humilde experiencia, las macros en Scheme se usan tanto como en otros Lisp, como Common Lisp o Clojure. Supongo que es una prueba de que tal vez las macros higiénicas no son una buena idea, y aquí estaría en desacuerdo con Paul Graham acerca de por qué. No es porque a veces quieras estar sucio (no higiénico) sino porque las macros higiénicas terminan siendo complejas o intrincadas.
"porque las macros higiénicas terminan siendo complejas o intrincadas" - No creo que esto se deba a la propia higiene; es más probable porque las macros higiénicas de Scheme son de "alto nivel" y deben escribirse en un lenguaje distinto de Scheme (que, en lo que a mí respecta, ¡es mucho menos conveniente que Scheme!) Es por eso que amo Common Lisp y todavía utilizo define-macro en Scheme, aunque R5RS tiene este truco de reglas de sintaxis ...:-) – Jay
Practical Common Lisp, por Peter Seibel, tiene una buena introducción a las macros. On Lisp, de Paul Graham, podría ser una buena fuente de ejemplos más complicados. Además, tenga en cuenta las macros integradas en, por ejemplo, Common Lisp.
Scheme macros! = Common Lisp macros –
Un ejemplo de una macro más avanzada que no es una forma de lambda en el encubrimiento es de Common Lisp macro con ranuras, lo que hace ranura objeto mirada acceso como ordinaria acceso a variables:
(with-slots (state door) car
(when (eq state :stopped)
(setq state :driving-around)
(setq door :closed)))
Tenga en cuenta que este no es lo mismo que vincular los valores de las ranuras a las variables locales y acceder a ellas, ya que con las ranuras le permite modificar las ranuras a través de SETQ y ver los cambios externos de inmediato.
The el uso de setq realmente está en desuso en favor de setf. Es menos confuso para los lectores nuevos (comunes) si ejemplos como este usan setf. – simon
Se necesitan macros para implementar nuevas estructuras de control y nuevas construcciones de enlace.
Por lo tanto, busque este tipo de construcciones en http://planet.plt-scheme.org. En PLaneT ambos navegan por la documentación y el código.
Ejemplos de nuevas estructuras de control:
http://planet.plt-scheme.org/package-source/soegaard/control.plt/2/0/planet-docs/manual/index.html
encontrar ejemplos de nuevas formas de unión, busque macros que comienzan con "con-". Un ejemplo útil se encuentra en math.plt también de PLaneT.
; Within a (with-modulus n form1 ...) the return values of
; the arithmetival operations +, -, * and^are automatically
; reduced modulo n. Furthermore (mod x)=(modulo x n) and
; (inv x)=(inverse x n).
; Example: (with-modulus 3 (^ 2 4)) ==> 1
(define-syntax (with-modulus stx)
(syntax-case stx()
[(with-modulus e form ...)
(with-syntax ([+ (datum->syntax-object (syntax with-modulus) '+)]
[- (datum->syntax-object (syntax with-modulus) '-)]
[* (datum->syntax-object (syntax with-modulus) '*)]
[^ (datum->syntax-object (syntax with-modulus) '^)]
[mod (datum->syntax-object (syntax with-modulus) 'mod)]
[inv (datum->syntax-object (syntax with-modulus) 'inv)])
(syntax (let* ([n e]
[mod (lambda (x) (modulo x n))]
[inv (lambda (x) (inverse x n))]
[+ (compose mod +)]
[- (compose mod -)]
[* (compose mod *)]
[square (lambda (x) (* x x))]
[^ (rec^(lambda (a b)
(cond
[(= b 0) 1]
[(even? b) (square (^ a (/ b 2)))]
[else (* a (^ a (sub1 b)))])))])
form ...)))]))
El documento Automata via Macros presenta una perla programación funcional en la implementación de máquinas de estados finitos a través de macros en el esquema.
El libro The Reasoned Schemer finaliza con una implementación completa en macro de miniKanren, el lenguaje de programación lógica utilizado en el libro. This paper presenta miniKanren y su implementación más formal y concisa que en el libro.
Ese enlace de Automata vía Macros es oro puro. ¡Tuve un gran aha! momento de leerlo. +1 de mi parte –
Los uso cuando los procedimientos no son suficientes.
Tuve una macro curry
cuando solía hacer muchos esquemas en mi palma. Fue muy útil.
Las macros de esquema le permiten agregar características que los autores del idioma original no incluían; esa es toda la filosofía detrás de las macros.
Aquí hay un pequeño ejemplo: PLT Scheme proporciona un lenguaje para escribir presentaciones llamadas Diapositivas. Usé macros para asociar un número de diapositiva con una diapositiva para poder administrarlos más fácilmente.
He escrito una macro que proporciona la sintaxis de infijo. Nada demasiado sofisticado; sin precedencia Aunque generalmente estoy de acuerdo con la sintaxis de prefijo, prefiero infix para < y>.
- 1. ¿Para qué has usado Object.clone()?
- 2. ¿Qué macros útiles has creado en Netbeans?
- 3. ¿Qué has usado para probar (funcional/cargar/estresar) tu servicio de red con su protocolo personalizado?
- 4. ¿Has usado boost :: tribool en el trabajo real?
- 5. ¿Para qué sirven las listas circulares (en Lisp o Scheme)?
- 6. ¿Has usado un algoritmo de vendedor ambulante para resolver un problema?
- 7. ¿Cuáles son las ventajas de las macros de esquema?
- 8. ¿Qué es & amp usado para
- 9. Fuentes para aprender sobre Scheme Macros: define-sintaxis y reglas de sintaxis
- 10. ACTION_SEND usado para enviar sms
- 11. expansión de macros para las macros con argumentos frente a las variables con el mismo nombre
- 12. ¿Alguien ha usado HipHop para PHP?
- 13. Primer Lisp con macros?
- 14. ¿Has utilizado JustCode?
- 15. ¿Qué hace que las macros de Lisp sean tan especiales?
- 16. ¿Qué git gotchas has sido atrapado?
- 17. ¿Dónde se almacenan las macros?
- 18. Entonces, ¿qué emocionantes algoritmos has "descubierto" recientemente?
- 19. Scheme Editor/IDE para Mac
- 20. ¿Cuál es la clase de constructor de toString más agradable que has usado o visto? Lo que lo hizo agradable
- 21. Mono para las macros del preprocesador de Android
- 22. ¿Qué debo hacer para que me paguen a Scheme?
- 23. uso de `else` en las macros
- 24. ¿Por qué necesito doble capa de indirección para macros? En
- 25. ¿Qué software se ha escrito en Scheme?
- 26. Borrar todas las macros vim actualmente definidas
- 27. Sobre la dependencia de las macros
- 28. ¿qué idioma necesito para escribir macros en LIbre Office Calc?
- 29. macros en macros
- 30. ¿Las macros variables no son estándar?
Esquema de PLT ahora llamado Racket. Ver http://www.racket-lang.org/ – Stephen