Let me explain what I am trying to achieve. It's basically generic
arithmetic. I have a `field' structure that contains functions on how to
add, subtract, etc field elements:
(defstruct (field (:conc-name field))
(+ #'+ :read-only t)
(- #'- :read-only t)
(* #'* :read-only t)
(/ #'/ :read-only t)
(-zero 0 :read-only t)
(-one 1 :read-only t))
(defconstant +default-field+
(make-field))
As typing
(funcall (field+ field) (field-one field) random-field-element)
would rapidly get tedious, I want to define a macro `with-field-ops'
so that I can write:
(with-field-ops field
(f+ f1 random-field-element))
I came up with this:
(defmacro with-field-ops (field &body body)
`(let ((ff+ (field+ ,field))
(ff- (field- ,field))
(ff* (field* ,field))
(ff/ (field/ ,field))
(f0 (field-zero ,field))
(f1 (field-one ,field)))
(declare (ignorable ff+ ff- ff* ff/ f0 f1))
(macrolet ((f+ (x y) `(funcall ff+ ,x ,y))
(f- (x y) `(funcall ff- ,x ,y))
(f* (x y) `(funcall ff* ,x ,y))
(f/ (x y) `(funcall ff/ ,x ,y)))
,@body)))
which is a bit cludgy, but works if I type it at the toplevel. However
if I chuck the above code in a "FIELD" package, this happens:
;; Loading file /home/mwh21/src/c2/16.1/field.lisp ...
;; Loading of file /home/mwh21/src/c2/16.1/field.lisp is finished.
T
CL-USER[9]> (use-package "FIELD")
T
CL-USER[10]> (with-field-ops +default-field+ (f+ f1 f0))
*** - EVAL: the function F+ is undefined
It's obvious why this happens:
CL-USER[13]> (macroexpand '(with-field-ops +default-field+ (f+ f1 f0)))
(LET
((FIELD::FF+ (FIELD+ +DEFAULT-FIELD+)) (FIELD::FF- (FIELD- +DEFAULT-FIELD+))
(FIELD::FF* (FIELD* +DEFAULT-FIELD+)) (FIELD::FF/ (FIELD/ +DEFAULT-FIELD+))
(FIELD::F0 (FIELD-ZERO +DEFAULT-FIELD+))
(FIELD::F1 (FIELD-ONE +DEFAULT-FIELD+))
)
(DECLARE
(IGNORABLE FIELD::FF+ FIELD::FF- FIELD::FF* FIELD::FF/ FIELD::F0 FIELD::F1)
)
(MACROLET
((FIELD::F+ (FIELD::X FIELD::Y) `(FUNCALL FIELD::FF+ ,FIELD::X ,FIELD::Y))
(FIELD::F- (FIELD::X FIELD::Y) `(FUNCALL FIELD::FF- ,FIELD::X ,FIELD::Y))
(FIELD::F* (FIELD::X FIELD::Y) `(FUNCALL FIELD::FF* ,FIELD::X ,FIELD::Y))
(FIELD::F/ (FIELD::X FIELD::Y) `(FUNCALL FIELD::FF/ ,FIELD::X ,FIELD::Y))
)
(F+ F1 F0)
) ) ;
T
But it's not obvious (to me) what to do about it... is what I'm doing
bad practice for some reason?
It's a bit like with-slots, I suppose.
TIA,
Michael
The "FIELD" package should export those symbols that you want to
`capture' in the body of WITH-FIELD-OPS, (namely F+, F-, F*, and F/)
Michael Hudson <·····@cam.ac.uk> wrote in message
···················@atrus.jesus.cam.ac.uk...
> Let me explain what I am trying to achieve. It's basically generic
> arithmetic. I have a `field' structure that contains functions on how to
> add, subtract, etc field elements:
>
> (defstruct (field (:conc-name field))
> (+ #'+ :read-only t)
> (- #'- :read-only t)
> (* #'* :read-only t)
> (/ #'/ :read-only t)
> (-zero 0 :read-only t)
> (-one 1 :read-only t))
>
> (defconstant +default-field+
> (make-field))
> As typing
>
> (funcall (field+ field) (field-one field) random-field-element)
>
> would rapidly get tedious, I want to define a macro `with-field-ops'
> so that I can write:
>
> (with-field-ops field
> (f+ f1 random-field-element))
>
> I came up with this:
>
> (defmacro with-field-ops (field &body body)
> `(let ((ff+ (field+ ,field))
> (ff- (field- ,field))
> (ff* (field* ,field))
> (ff/ (field/ ,field))
> (f0 (field-zero ,field))
> (f1 (field-one ,field)))
> (declare (ignorable ff+ ff- ff* ff/ f0 f1))
> (macrolet ((f+ (x y) `(funcall ff+ ,x ,y))
> (f- (x y) `(funcall ff- ,x ,y))
> (f* (x y) `(funcall ff* ,x ,y))
> (f/ (x y) `(funcall ff/ ,x ,y)))
> ,@body)))
>
> which is a bit cludgy, but works if I type it at the toplevel. However
> if I chuck the above code in a "FIELD" package, this happens:
>
> ;; Loading file /home/mwh21/src/c2/16.1/field.lisp ...
> ;; Loading of file /home/mwh21/src/c2/16.1/field.lisp is finished.
> T
> CL-USER[9]> (use-package "FIELD")
> T
> CL-USER[10]> (with-field-ops +default-field+ (f+ f1 f0))
> *** - EVAL: the function F+ is undefined
>
> It's obvious why this happens:
>
> CL-USER[13]> (macroexpand '(with-field-ops +default-field+ (f+ f1 f0)))
> (LET
> ((FIELD::FF+ (FIELD+ +DEFAULT-FIELD+)) (FIELD::FF- (FIELD-
+DEFAULT-FIELD+))
> (FIELD::FF* (FIELD* +DEFAULT-FIELD+)) (FIELD::FF/ (FIELD/
+DEFAULT-FIELD+))
> (FIELD::F0 (FIELD-ZERO +DEFAULT-FIELD+))
> (FIELD::F1 (FIELD-ONE +DEFAULT-FIELD+))
> )
> (DECLARE
> (IGNORABLE FIELD::FF+ FIELD::FF- FIELD::FF* FIELD::FF/ FIELD::F0
FIELD::F1)
> )
> (MACROLET
> ((FIELD::F+ (FIELD::X FIELD::Y) `(FUNCALL FIELD::FF+ ,FIELD::X
,FIELD::Y))
> (FIELD::F- (FIELD::X FIELD::Y) `(FUNCALL FIELD::FF- ,FIELD::X
,FIELD::Y))
> (FIELD::F* (FIELD::X FIELD::Y) `(FUNCALL FIELD::FF* ,FIELD::X
,FIELD::Y))
> (FIELD::F/ (FIELD::X FIELD::Y) `(FUNCALL FIELD::FF/ ,FIELD::X
,FIELD::Y))
> )
> (F+ F1 F0)
> ) ) ;
> T
>
> But it's not obvious (to me) what to do about it... is what I'm doing
> bad practice for some reason?
>
> It's a bit like with-slots, I suppose.
>
> TIA,
> Michael
"Joe Marshall" <·········@alum.mit.edu> writes:
> The "FIELD" package should export those symbols that you want to
> `capture' in the body of WITH-FIELD-OPS, (namely F+, F-, F*, and F/)
Thanks. Obvious, but I still wouldn;t have thought of it for some
time, methinks.
Cheers,
Michael