2008-12-04 7 views
5

Puede una macro escribirse en el Esquema (con define-syntax, por ejemplo) que se llevará a expresiones como ésta:macro Esquema de manifestación de anidación

(op a b c d e f g h i j) 

y el rendimiento expresiones como ésta como salida?

(op (op (op (op (op (op (op (op (op a b) c) d) e) f) g) h) i) j) 

Por supuesto, para longitudes arbitrarias. No puedo pensar en una manera de hacerlo, dado alguna plantilla de la siguiente manera:

(define-syntax op 
    (syntax-rules() 
    [(_) 'base-case] 
    [(v1 v2 ...) 'nested-case??])) 
+0

Tengo curiosidad. ¿Fue solo una cuestión de interés teórico o tiene un caso de uso interesante? En general, ese tipo de envoltura se lograría con un foldLeft. – namin

+0

hmm, buen punto. Principalmente le pregunté esto porque no pensé en tu camino = P. No me di cuenta de que esto es exactamente lo que hace foldl. – Claudiu

Respuesta

6
(define bop list) 

(define-syntax op 
    (syntax-rules() 
    ((op a b) (bop a b)) 
    ((op a b c ...) (op (bop a b) c ...)))) 

Por ejemplo, (op 1 2 3 4) se expande a (bop (bop (bop 1 2) 3) 4) y evalúa a (((1 2) 3) 4).

+1

¿Por qué está utilizando bop en los identificadores literales si no lo está haciendo? – leppie

+0

Buen punto. Fijo. – namin

+1

las macros de esquema son realmente muy inteligentes con sus ... ¿no? – Claudiu

0

para mostrar cómo la respuesta se resuelve:

(op 1 2 3 4) 

Este es un artículo con 4 estados, por lo que el segundo caso se selecciona con a = 1, b = 2, c = 3, ... = 4:

(op (bop 1 2) 3 4) 

Esta es una operación con 3 afirmaciones, por lo que el segundo caso nuevamente. a = (BOP 1 2), b = 3, c = 4:

(op (bop (bop 1 2) 3) 4) 

Ahora bien, este es un BOP con 2 estados, por lo que un = (BOP (base de la pirámide 1 2) 3), b = 4, y está hecho.

1

La función que desea aplicar a los argumentos debería ser un argumento para la macro. Salvo eso, mi solución fue la misma.

#!r6rs 

(import (rnrs base)) 

(define-syntax claudiu 
    (syntax-rules() 
    ((claudiu fun first second) 
    (fun first second)) 
    ((claudiu fun first second rest ...) 
    (claudiu fun (claudiu fun first second) rest ...))))