Thanks David,

  I actually ended up ending up a generic macro destructurer like the one you have above (except it's not hard coded to anything, it looks at the first elem of the list (whether it's a cons, a p3, a ...) then figures out how to destructure it based on that. Fairly ugly macro, but elegant to use.

On Tue, Jun 2, 2009 at 5:36 AM, David St-Hilaire <sthilaid@iro.umontreal.ca> wrote:
lowly coder wrote:
Suppose I have the following:

(define-type p3 x y z)

(define (with-cons c func) (func (car c) (cdr c))))

(define (with-p3 p func) (func (p3-x p) (p3-y p) (p3-z p)))

(define p (cons (make-p3 1 2 3) (make-p3 4 5 6)))

Now, ideally I want to write:

(destructure-bind (cons (p3 x1 y1 z1) (p3 x2 y2 z2))
 (make-point3 (+ x1 x2) (+ y1 y2) (+ z1 z2)))

How can I do this with with-cons / with-p3? (It seems I can only go done one level of nesting).
I think you might want to investigate time into using an object system with generic functions... Gambit's define-type is juste a raw data container with not much meat around it...

That said, if the usage your mentionning is just want you want to do, then you can hardcode the macro for pairs of p3 objects:

(define-macro (destructure-bind pair-p3 . body)
  (let ((arg (gensym 'arg))
    (p1 (gensym 'p1))
    (p2 (gensym 'p2)))
    `(let* ((,arg ,pair-p3)
        (,p1 (car ,arg))
        (,p2 (cdr ,arg))
        (x1 (p3-x ,p1))
        (y1 (p3-y ,p1))
        (z1 (p3-z ,p1))
        (x2 (p3-x ,p2))
        (y2 (p3-y ,p2))
        (z2 (p3-z ,p2)))
   ,@body)))

> (destructure-bind (cons (make-p3 1 2 3) (make-p3 4 5 6))
          (make-p3 (+ x1 x2) (+ y1 y2) (+ z1 z2)))

#<p3 #6 x: 5 y: 7 z: 9>

I hope it can help you...

David