2010-05-01 17 views
6

que a menudo se encuentran los siguientes tipos de definición incrementales útil:¿Es posible la definición incremental de Macro?

(define (foo) (display "bar")) 
(foo) 
;prints bar 
(define foo (let ((bar foo)) 
       (lambda() 
       (display "foo") 
       (bar)))) 

(foo) 
;prints foobar 

¿Cómo preforma de este tipo de definición incrementales con macros? No pude obtener la sintaxis let para proporcionar la misma funcionalidad.

Actualmente uso PLT Scheme, pero les gustaría ver respuestas en diferentes implementaciones de Lisp también.

Editar:

Ingenuamente me gustaría hacer lo siguiente:

(define-syntax foo 
    (syntax-rules() 
    ((_) (display "bar")))) 

(define-syntax foo 
    (let-syntax ((old-foo (syntax-rules() ((_) (foo))))) 
    (syntax-rules() 
     ((_) (begin 
      (display "foo") 
      (old-foo)))))) 

Traducción de macros ingenuos al trabajo macros PLT Scheme:

(require-for-syntax scheme/base) 
(define-syntax foo 
    (syntax-rules() 
    [(foo) (display "bar")])) 
(define-syntax foo 
    (let ([old (syntax-local-value #'foo)]) 
    (lambda (stx) 
     #`(begin #,((syntax-rules() 
       [(_) (begin (display "foo"))]) stx) 
      #,(old #'(_)))))) 
(foo) 

Si me falta un mejor método Házmelo saber.

Respuesta

2

Fwiw (y esto es definitivamente no mucho, ya que esto es más o menos un ejercicio de destino practicando con los pies), aquí es cómo se podría hacer esto en el Esquema PLT con sólo higiénicas syntax-rules macros:

(define-syntax foo 
    (syntax-rules() 
    [(foo x) (list 'x '= x)])) 
(define-syntax foo 
    (let ([old (syntax-local-value #'foo)]) 
    (compose (syntax-rules() 
       [(_ x ...) (list 'begin x ... 'end)]) 
      old))) 
(printf ">>> ~s\n" (foo (+ 1 2))) 

Esto no funcionará dentro de un módulo, solo en el REPL - y eso es bueno cosa. También es posible hacer algo similar en los módulos, pero si quieres hacerlo, también puedes usar macros de procedimiento (también conocidas como macros syntax-case), con un identificador vinculado al nivel de sintaxis y `set! '- ing su valor para extenderlo. Todavía no es una gran idea, y aún puede llevar a sangrar los ojos, pero a algunas personas les gusta lastimarse a sí mismas ...

(Ah, y por cierto - incluso haciendo esto sigue siendo totalmente sin relación a si las macros en cuestión son higiénicas o no.)

+1

Gracias, tuve que incluir (requiere esquema/base de sintaxis) para hacer que la composición se defina en la fase de sintaxis (para hacer que la composición se defina dentro de la sintaxis de definición). ¿Puedes comentar sobre mi enfoque ingenuo (agregado a la pregunta) que no está implementado? ¿El tiempo no es práctico o cómo es inconsistente con la sintaxis existente? – Davorak

+1

Sí, necesita 'scheme/base' para componer; pero puede combinar funciones de macro de la forma que desee, son solo funciones de sintaxis a sintaxis, y 'sintaxis-reglas' es una macro conveniente (segundo nivel, por lo general) que genera dichas funciones. En cuanto a su enfoque ingenuo, adolece de algunos problemas fundamentales: trata de capturar de alguna manera la sintaxis anterior, pero no puede obtener su * valor * de esta manera, por lo que el resultado es una macro que se expande a llamadas a sí mismo. Otro problema es tratar de usar 'display' para depurar cosas: las macros * no * lo harán, * se * expandirán * a él. –

+0

Gracias, sabía que no podía capturar la sintaxis antigua de esta manera y que se expandiría en sí misma. Simplemente pensé que era muy parecida a una sintaxis con la que estaba familiarizado y me pregunté por qué, dado que existía en el nivel de funciones, por qué no existía a nivel macro, aunque no parecía haber nada fundamental que impidiera que un compilador actuara de esa manera. Estaba tratando de usar la pantalla como una prueba para ver si la macro se construyó correctamente, edité mi pregunta una traducción de mi macro ingenua a una macro de esquema plt en funcionamiento. – Davorak

3

Con macros de esta manera usted es en la forma de crear los más difíciles de mantener el software en el planeta.

Editar: en Common Lisp es posible. No puedo recordar que alguna vez lo haya visto usado en el código fuente.

Adición de comportamiento para funciones o macros es a menudo llamado 'consejo' o 'consejos' en la comunidad Common Lisp. Algunas herramientas 'asesorar' también tienen la capacidad de aconsejar macros.

+0

Actualmente no programo con el esquema tiene nada que ver con la misión crítica o incluso mi personal flujo de trabajo También la definición incremental que tengo arriba podría convertirse fácilmente en un decorador de funciones parecido a Python. Entonces, otra forma de redactar mi pregunta sería ¿son posibles los macro decoradores? – Davorak

+0

@Davorak: ¿decoras decoradores? – outis

+0

En Python los decoradores se pueden usar en la definición del decorador, aunque no he tenido la oportunidad de usarlos de esa manera en mi propio código. Veo cómo podría ser útil hacerlo. Solo para asegurarme de que mi comentario anterior estaba claro, lo que quería decir con Macro Decorator era una macro que podría usarse para decorar otra macro. – Davorak

3

No creo que pueda hacer algo como esto con las macros. Tampoco veo ningún sentido al intentarlo.

Tenga en cuenta que macros no son sólo algunas funciones extra de magia con! Las macros son algo completamente diferente.

Tal vez usted está buscando algo así como combinaciones de métodos en Common Lisp?

+0

Gracias. ¿Tampoco ves el punto en el caso funcional? ¿O el caso de los decoradores en python? ¿Es útil en ninguna parte? ¿O por qué no es útil para las macros en particular? ... Ahora que he leído un poco sobre las combinaciones de métodos, parecen proporcionar la misma funcionalidad de decoradores en python. ¿Por qué este nivel de abstracción es útil para las funciones pero no tiene sentido para las macros? – Davorak

+0

@Davorak: los decoradores son distintos en funcionalidad de las combinaciones de métodos. Los decoradores se ejecutan en la definición, mientras que los métodos combinados se ejecutan cuando se llama al método. Los últimos son una parte esencial de la Programación Orientada a Aspectos. En todo caso, los decoradores son más similares a las macros, pero se usan en circunstancias más limitadas. – outis

+0

Lo que parece describir es una diferencia de implementación, no una diferencia de funcionalidad. Puedo usar un decorador para ejecutar código adicional antes, después o alrededor de una función o anularla por completo. Esto es exactamente como las combinaciones de métodos en mi comprensión de la lectura de la especificación, que puede utilizar una combinación de métodos para ejecutar código adicional antes, después o alrededor de una función existente. – Davorak

0

¿Qué hay de let*?

(define foobar 
    (let* ((foo (lambda() (display "foo"))) 
      (bar (lambda() (foo) (display "bar")))) 
      bar)) 
+0

Gracias, pero creo que no entendieron la pregunta. Estaba interesado en poder cambiar la definición de la variable global, mientras que lo anterior solo es local. Además, mi pregunta era cómo es posible hacerlo con macros. – Davorak

1

Creo que se podría conseguir mediante el uso de macros higiénicas, que creo que es compatible con PLT Scheme. Entonces usaría exactamente los mismos mecanismos que con las funciones regulares, ya que las macros serían funciones regulares que operaban en S-expressions.

No sé cómo hacer esto con macros higiénicas, pero estoy bastante sorprendido de que no se puede - Yo consideraría preguntar en una lista de correo PLT.

+0

Gracias, intentaré consultar la lista de correo en algún momento. Todavía me sorprendería si fuera posible con macros antihigiénicos en plt, pero contento. Intenté hacer una respuesta con defmacro, pero no he podido encontrar una respuesta, aunque no soy experto en defmacro. – Davorak

+2

Es * posible * hacer en PLT - la clave no está en las macros que son higiénicas o no, sino con una macrocapa de procedimiento y algunas capacidades reflexivas que la acompañan. –

Cuestiones relacionadas