views:

342

answers:

3

Can a macro be written in Scheme (with define-syntax, for example) which will take expressions like this:

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

And yield expressions like this as output?

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

Of course, for arbitrary lengths. I can't think of a way to do it, given some template like this:

(define-syntax op
  (syntax-rules ()
    [(_) 'base-case]
    [(v1 v2 ...) 'nested-case??]))
+6  A: 
(define bop list)

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

For example, (op 1 2 3 4) expands to (bop (bop (bop 1 2) 3) 4) and evaluates to (((1 2) 3) 4).

namin
Why are you using bop in the literal identifiers if you are not matching it?
leppie
Good point. Fixed.
namin
scheme macros are really really smart with their ... aren't they?
Claudiu
A: 

To show how the answer works out:

(op 1 2 3 4)

This is an op with 4 statements, so the 2nd case gets selected with a=1, b=2, c=3, ...=4:

(op (bop 1 2) 3 4)

This is an op with 3 statements, so 2nd case again. a=(bop 1 2), b=3, c=4:

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

Now this is a bop with 2 statements, so a=(bop (bop 1 2) 3), b=4, and it's done.

Claudiu
+1  A: 

The function you want to apply to the arguments should itself be an argument to the macro. Barring that, my solution was the same.

#!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 ...))))
grettke