Hi,
I want to write a little language for optical ABCD matrix computation.
At present this is just
for learning Lisp and macros especially.
I define a class abcd:
(defclass abcd () ((a :initform 1.0 :initarg :a :accessor a) (b
:initform 0.0 :initarg :b :accessor b)
(c :initform 0.0 :initarg :c :accessor c) (d
:initform 1.0 :initarg :d :accessor d))
(:default-initargs :a 1.0 :b 0.0 :c 0.0 :d 1.0))
Then I define a macro that I would like to make the job of defining
optical elements like
lenses, mirrors and so on:
(defmacro def-oe (oe-type y)
`(progn
(defclass ,oe-type (abcd) ((,y :initform 1.0 :initarg :f
:accessor ,y)))
(defmethod initialize-instance :after ((,oe ,oe-type) &rest
initargs)
(setf (c ,oe) (/ -1.0 (,y ,oe)))) ;in the final version this
should also be given as a macro parameter
(defmacro ,oe-type (name &key ,y)
`(setf ,name (make-instance ',,oe-type :f ,y)))))
I faced two problems:
1. I could not figure out how to make the macro expand initarg :f into
something like :,y.
The same for :f ,y in `(setf ,name ..)
2. When I type
(def-oe lens f)
(lens l1 :f 100.0)
I get the error message:
*** - EVAL: variable LENS has no value
I'm running CLISP under WinNT.
Thanks in anticipation.
Rolf Wester
Rolf Wester <······@ilt.fhg.de> writes:
> (defclass abcd ()
> ((a :initform 1.0 :initarg :a :accessor a)
> (b :initform 0.0 :initarg :b :accessor b)
> (c :initform 0.0 :initarg :c :accessor c)
> (d :initform 1.0 :initarg :d :accessor d))
> (:default-initargs :a 1.0 :b 0.0 :c 0.0 :d 1.0))
>
> Then I define a macro that I would like to make the job of defining
> optical elements like lenses, mirrors and so on:
>
> (defmacro def-oe (oe-type y)
> `(progn
> (defclass ,oe-type (abcd)
> ((,y :initform 1.0 :initarg :f :accessor ,y)))
> (defmethod initialize-instance :after
> ((,oe ,oe-type) &rest initargs)
> ;; in the final version this should also be given
> ;; as a macro parameter
> (setf (c ,oe) (/ -1.0 (,y ,oe))))
> (defmacro ,oe-type (name &key ,y)
> `(setf ,name (make-instance ',,oe-type :f ,y)))))
It's unlikely that ,y is going to work here. I didn't try your code, but
you plainly mean the "y" from two backquotes out, so that'd be ,',y
probably.
> I faced two problems:
> 1. I could not figure out how to make the macro expand initarg :f into
> something like :,y. The same for :f ,y in `(setf ,name ..)
: is not a readmacro. It is a primitive piece of token syntax.
:FOO denotes the symbol named "FOO" in the package "KEYWORD".
If you have instead the symbol FOO, you must take its name with
SYMBOL-NAME, as in (SYMBOL-NAME 'FOO) => "FOO", then you must
intern it anew in the keyword package, as in (INTERN "FOO" "KEYWORD").
But I don't recommend that. I recommend that the macro call be given the
keyword symbol in the first place OR that you use a non-keyword as an
init arg. e.g., arrange to do (def-oe lens f :f) or else arrange to use
f rather than :f as an initarg. Nothing is wrong with a slotspec like
(foo :initform 1 :initarg foo :accessor foo)
You just have to do (make-instance .... 'foo 2)
rather than (make-instance .... :foo 2).
As such, you could just use
((,y :initform 1.0 :initarg ,y :accessor ,y))
and
`(setf ,name (make-instance ',,oe-type ',',y ,',y)))))
> 2. When I type
> (def-oe lens f)
> (lens l1 :f 100.0)
> I get the error message:
> *** - EVAL: variable LENS has no value
I'm guessing this might be because of your use of ',,oe-type which says
to evaluate oe-type's result once before not doing so. That is, you put
in LENS, then at one backquote level you evaluate LENS and at the other
backquote level you don't evaluate it. I think you want to evaluate it
at neither level, so you want ',',oe-type instead. I'm just guessing though.
It's late and I'm sleepy and too lazy to type this in and try it.
> I'm running CLISP under WinNT.
>
> Thanks in anticipation.
>
> Rolf Wester
Rolf Wester <···········@t-online.de> writes:
> Hi,
>
> thanks a lot to Kent and Kenny for your comprehensive replies. Below I
> attach
> the versions I tried along the suggestions given by you. Maybe there are
> more
> Lisp (Lips macro) beginners who are interested in it.
>
> Lisp macros are really a fascinating kind of higher order programming.
>
> Rolf Wester
>
> ----------------------------------------------------------------------------------
>
> (defclass abcd () ((a :initform 1.0 :initarg :a :accessor a)
> (b :initform 0.0 :initarg :b :accessor b)
> (c :initform 0.0 :initarg :c :accessor c)
> (d :initform 1.0 :initarg :d :accessor d))
> (:default-initargs :a 1.0 :b 0.0 :c 0.0 :d 1.0))
If you are using both :initarg's and :initform's with the same
constant values, maybe you can do away with the second ones.
(defclass abcd ()
((a :initarg :a :accessor a)
(b :initarg :b :accessor b)
(c :initarg :c :accessor c)
(d :initarg :d :accessor d))
(:default-initargs :a 1.0 :b 0.0 :c 0.0 :d 1.0))
Cheers
--
Marco Antoniotti ========================================================
NYU Courant Bioinformatics Group tel. +1 - 212 - 998 3488
719 Broadway 12th Floor fax +1 - 212 - 995 4122
New York, NY 10003, USA http://bioinformatics.cat.nyu.edu
"Hello New York! We'll do what we can!"
Bill Murray in `Ghostbusters'.