Macro doesn't work in the function.

Posted by avp on Stack Overflow See other posts from Stack Overflow or by avp
Published on 2010-03-26T12:22:47Z Indexed on 2010/03/26 16:23 UTC
Read the original article Hit count: 619

Filed under:
|

I have problems with following code: http://lisper.ru/apps/format/96

The problem is in "normalize" function, which does not work.
It fails on the fifth line: (zero-p a indexes i)

(defun normalize (a &optional indexes i)
  "Returns normalized A."
  (pragma
   (format t "Data=~A ~A ~A" a indexes i)
   (if (zero-p a indexes i)
      a ;; cannot normalize empty vector
    (let* ((mmm (format t "Zero?=~a" (zero-p a indexes i)))
             (L (sqrt (+ (do-op-on * a :x a :x indexes i indexes i)
                         (do-op-on * a :y a :y indexes i indexes i)
                         (do-op-on * a :z a :z indexes i indexes i))))
             (mmm (format t "L=~a" L))
             (L (/ 1D0 L))
             (mmm (format t "L=~a" L))) ; L=1/length(A)
      (make-V3 (* (ref-of a :x indexes i) l)
                 (* (ref-of a :y indexes i) l)
                 (* (ref-of a :z indexes i) l))))))

in function "normalize" I call the macro "zero-p", which in turn calls macro "ref-of", which is the last in the chain.

(defmacro zero-p (v &optional indexes index)
  "Checks if the vector is 'almost' zero length."
  `(and (< (ref-of ,v :x ,indexes ,index) *min+*)
    (< (ref-of ,v :y ,indexes ,index) *min+*)
    (< (ref-of ,v :z ,indexes ,index) *min+*)
    (> (ref-of ,v :x ,indexes ,index) *min-*)
    (> (ref-of ,v :y ,indexes ,index) *min-*)
    (> (ref-of ,v :z ,indexes ,index) *min-*)))

Here is ref-of:

(defmacro ref-of (values coordinate &optional indexes index)
  "Please see DATA STRUCTURE for details."
  (if indexes
       (cond ((eq coordinate :x) `(aref ,values (aref ,indexes ,index)))
        ((eq coordinate :y) `(aref ,values (+ 1 (aref ,indexes ,index))))
        ((eq coordinate :z) `(aref ,values (+ 2 (aref ,indexes ,index))))
        (T (error "The symbol ~S is not :X, :Y or :Z." coordinate)))
       (cond ((eq coordinate :x) `(aref ,values 0))
    ((eq coordinate :y) `(aref ,values 1))
        ((eq coordinate :z) `(aref ,values 2))
        (T (error "The symbol ~S is not :X, :Y or :Z." coordinate)))))

Also, in "normalize" I call the macro "do-op-on", which calls "ref-of" as well.

(defmacro do-op-on (op name1 coord1 name2 coord2 &optional is1 i1 is2 i2)
  "Example: (do-op-on * A :x B :y i n) == A[i[n]].x*B.y"
  `(,op (ref-of ,name1 ,coord1 ,is1 ,i1) (ref-of ,name2 ,coord2 ,is2 ,i2)))

As a result, instead of having this: (aref some-array 0) I have (aref NIL NIL) which is created in "ref-of".

I suppose that I lose the symbol A from the call (normalize A). I just feel that the symbol does not survive the macroexpanson. The thing is, macroexpansoin works in REPL for each macro independently.

Can anyone explain where is the mistake?

© Stack Overflow or respective owner

Related posts about lisp

Related posts about macros