[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.lisp

Re: help a newbie with a macro

William James

4/6/2015 4:00:00 AM

Barry Margolin wrote:

> > I'm working on my Lisp raytracer (mainly to learn Lisp), and I came
> > across an opportunity to remove code dupe: Vector functions. Most
> > vector functions tend to like something like this:
> >
> > (defun dot-product (a b)
> > (+ (* (v-x a) (v-x b))
> > (* (v-y a) (v-y b))
> > (* (v-z a) (v-z b))))
> >
> > As you can see, the duplication comes when you have to do the same
> > thing for all three components. I would like some macro, perhaps
> > called 'for-each-comp', that would let me do something like this:
> >
> > (defun dot-product (a b)
> > (+ (for-each-comp (v-c)
> > (* (v-c a) (v-c b)))))
> >
> > The macro should make three copies of the *-form, and for each replace
> > v-c with v-x or v-y or v-z. What's the best way to do this? I've
> > tossed around some ideas..but nothing strikes me as "the right way."
>
> (defmacro combine (obj1 obj2 outer-op inner-op &rest field-ops)
> (let ((obj1-var (gensym))
> (obj2-var (gensym)))
> `(let ((,obj1-var ,obj1)
> (,obj2-var ,obj2))
> (,outer-op
> ,@(loop for op in field-ops
> collect `(,inner-op (,op ,obj1-var)
> (,op ,obj2-var)))))))
>
> (defun dot-product (a b)
> (combine a b + * v-x v-y v-z))
>
> With a little redesign it can be made to handle an arbitrary number of
> arguments, rather than being hardcoded for 2.

Gauche Scheme:

(define (map-fields op . objects)
(apply vector-map
op
(map
(lambda (ob)
(vector-map (lambda (name) (ref ob name))
(rtd-field-names (class-of ob))))
objects)))


(use gauche.record)
(define-record-type point #t #t x y z)

(map-fields * (make-point 2 3 4) (make-point 10 100 1000))

===>
#(20 300 4000)