Infix.lsp as macro

Q&A's, tips, howto's
Locked
hds1
Posts: 28
Joined: Thu Mar 20, 2014 5:02 pm

Infix.lsp as macro

Post by hds1 »

Hi,
is it possible to transform the infix.lsp to a "true" macro i.e. doing the work at compile time ?
Or do i miss a critical point there ?
Calling "eval" during runtime is supposed to be expensive (at least in other lisps). Not sure how newlisp handles eval.
Reason for asking is that i redo some of the quaternion calculus as well as geographic math scripts.

i.e.
(INFIX:xlate "εk2 = aekb1 - aejbi + aeibj + aebk + akbe - ajbei + aibej + a1bek")
--> (setq εk2 (add (add (sub (add (add (add (sub aekb1 aejbi) aeibj) aebk) akbe) ajbei)
aibej) a1bek))
(INFIX:xlate "e3Xe4_x = sin(y3 - y4) * sin((x3 + x4) / 2) * cos((x3 - x4) / 2) - sin(y3 + y4) * cos((x3 + x4) / 2) * sin((x3 - x4) / 2)")
--> (setq e3Xe4_x (sub (mul (mul (sin (sub y3 y4)) (sin (div (add x3 x4) 2))) (cos (div (sub x3 x4) 2)))

I still can't wrap my mind around the lisp math syntax ... old school i fear ...

ralph.ronnquist
Posts: 228
Joined: Mon Jun 02, 2014 1:40 am
Location: Melbourne, Australia

Re: Infix.lsp as macro

Post by ralph.ronnquist »

You may do this kind of thing in two steps. Firstly, you define a macro, e.g.

Code: Select all

> (macro (mix) nil)
(lambda-macro () (expand 'nil))
Thereafter you redefine it to perform the "xlate" call the way you want it, e.g.

Code: Select all

> (constant 'mix (lambda-macro () (INFIX:xlate (join (map string (args)) " "))))
(lambda-macro () (INFIX:xlate (join (map string (args)) " ")))
Now you can use this in new definitions and expressions with "read-time" xlate-ion. E.g.,

Code: Select all

> (define (foo a b) (mix a +  b))
(lambda (a b) (add a b))
> '(mix 4 * 5 + sin(34) * 8 )
(add (mul 4 5) (mul (sin 34) 8))
> (mix 4 * 5 + sin(34) * 8 )
24.23266148896019
Of course, you might want to name it something else than 'mix.

hds1
Posts: 28
Joined: Thu Mar 20, 2014 5:02 pm

Re: Infix.lsp as macro

Post by hds1 »

thanks a ton. I must admit that i would never ever thought of a redefiniton.
Can you explain why the macro becomes "executable" due to the redefiniton ?

ralph.ronnquist
Posts: 228
Joined: Mon Jun 02, 2014 1:40 am
Location: Melbourne, Australia

Re: Infix.lsp as macro

Post by ralph.ronnquist »

Well, being or not being a macro is, I believe, some flag attached to the symbol, which is set by the "(macro ..)" term. That term also wraps the given "body" into an "expand" term, as is typically useful for these kinds of macros. But not in this case, where you want the xlate-ion to be invoked at read time.

The "(constant ...)" term simply attaches a new definition to the symbol without messing with the flag, and thus redefines it. The manual has some discussion about this point.

hds1
Posts: 28
Joined: Thu Mar 20, 2014 5:02 pm

Re: Infix.lsp as macro

Post by hds1 »

Exactly what is needed. Thx.
A minor setback is that infix.lsp does not handle "-" with one argument.
Math code is much clearer now.
Proof of expansion during read time attached.

Code: Select all

(load "infix.lsp")

(macro (mix) nil)
(constant 'mix (lambda-macro ()
		 (INFIX:xlate (join (map string (args)) " "))))

(define (quatmul q1 q2)
  (let ((x1 (nth 0 q1))	(y1 (nth 1 q1))	(z1 (nth 2 q1)) (w1 (nth 3 q1))
	(x2 (nth 0 q2))	(y2 (nth 1 q2))	(z2 (nth 2 q2)) (w2 (nth 3 q2)))
    (mix w = 0 - x1 * x2 - y1 * y2 - z1 * z2 + w1 * w2)
    (mix x =     x1 * w2 + y1 * z2 - z1 * y2 + w1 * x2)
    (mix y = 0 - x1 * z2 + y1 * w2 + z1 * x2 + w1 * y2)
    (mix z =     x1 * y2 - y1 * x2 + z1 * w2 + w1 * z2)))

(quatmul '(1 2 3 4) '(-9 -4 4 4)) --> Should be 42
(string (source 'quatmul))

==>
(define (quatmul q1 q2)
(let ((x1 (nth 0 q1)) (y1 (nth 1 q1)) (z1 (nth 2 q1)) (w1 (nth 3 q1))
       (x2 (nth 0 q2)) (y2 (nth 1 q2)) (z2 (nth 2 q2)) (w2 (nth 3 q2)))
(setq w (add (sub (sub (sub 0 (mul x1 x2)) (mul y1 y2)) (mul z1 z2)) (mul w1 w2)))
(setq x (add (sub (add (mul x1 w2) (mul y1 z2)) (mul z1 y2)) (mul w1 x2)))
(setq y (add (add (add (mul (sub 0 x1) z2) (mul y1 w2)) (mul z1 x2)) (mul w1 y2)))
(setq z (add (add (sub (mul x1 y2) (mul y1 x2)) (mul z1 w2)) (mul w1 z2)))))

Locked