[plt-scheme] Macro question

From: David Van Horn (dvanhorn at cs.uvm.edu)
Date: Sat May 24 16:34:11 EDT 2003

mcj4 at ukc.ac.uk wrote:

> Having the 'vec.name' naming is important to me, both practically and so I understand 
> better how to lexically introduce new names into the environment with a macro. However, 
> I can certainly work with what you tossed out, and it wins points for clarity.
> 
> M

Ok.  How's this?

(define-syntax (bind stx)
  (syntax-case stx ()
    ((_ ([v c1 c2 ...] ...) e ...)
     (with-syntax ((((v.c1 v.c2 ...) ...)
                    (datum->syntax-object
                     stx
                     (map (lambda (clause)
                            (map (lambda (x)
                                   (symbol-dot-symbol (car clause) x))
                                 (cdr clause)))
                          (syntax-object->datum #'((v c1 c2 ...) ...))))))

       #'(let-values ([(v.c1 v.c2 ...)
                       (let ((n (length '(c1 c2 ...))))
                         (vector->values (vector-take v n)))]
                      ...)
           e ...)))))

SYMBOL-DOT-SYMBOL has type (symbol symbol) -> symbol, with the obvious
meaning, and needs to be bound in the transformer environment of BIND.

VECTOR-TAKE is from SRFI 43.

This syntax, unlike the first solution I had, makes an assumption about v in
(bind ([v c1 c2 ...] ...) ...).  v must be an identifier that is bound to a
vector.  So you couldn't write eg, (bind (((make-vector 5) c1)) ...), but I
guess that's what you want. :)

Also, my previous solution required a binding for each value in a vector, this
version allows you to bind the leftmost N values of a vector where N <=
vector-length v.

Calculating N could be done at compile-time, but here it's not.  I couldn't
get that to work right, so I'd be interested in such a solution.

-d



Posted on the users mailing list.