Is it portable to use MAKE-LOAD-FORM to dump the results of a
macroexpansion? I'm too dense to understand 3.2.4.4.
I'm using something that does roughly
(defstruct foo
stuff
)
(defmethod make-load-form ((foo foo) &optional env)
(declare (ignore env))
(make-load-form-saving-slots foo))
(defmacro define-foo (name &rest stuff)
`(defparameter ,name ,(make-foo :stuff (mapcar #'eval stuff))))
except that the STUFF is the result of a lengthy computation that I
really want to happen at compile-time, not at load-time[1]. It
appears to work in both CMUCL and CLISP, but I'd like to know whether
I'll get in trouble with other implementations.
Another question: where do I find the set of built-in types that the
fasdumper is guaranteed to be able to dump? I've found, to my great
dismay, that while CLISP can dump compiled functions, CMUCL cannot:
(define-foo *foo* #'list)
...
; In: DEFINE-FOO *FOO*
; (DEFINE-FOO *FOO* #'LIST)
; --> DEFPARAMETER PROGN SETQ SETQ #S(FOO :STUFF (#<Function LIST {1010A4E1}>))
; --> PROGN PROGN SETF PCL::SET-SLOT-VALUE PCL::ACCESSOR-SET-SLOT-VALUE LET
; ==>
; '(#<Function LIST {1010A4E1}>)
; Error: Cannot dump objects of type FUNCTION into fasl files.
;
Thanks for your help,
Juliusz
Juliusz Chroboczek wrote:
> Is it portable to use MAKE-LOAD-FORM to dump the results of a
> macroexpansion?
Yes, if the result doesn't contain literal objects of "weird" type.
> I'm using something that does roughly
>
> (defstruct foo
> stuff
> )
>
> (defmethod make-load-form ((foo foo) &optional env)
> (declare (ignore env))
> (make-load-form-saving-slots foo))
>
> (defmacro define-foo (name &rest stuff)
> `(defparameter ,name ,(make-foo :stuff (mapcar #'eval stuff))))
>
> except that the STUFF is the result of a lengthy computation that I
> really want to happen at compile-time, not at load-time[1]. It
> appears to work in both CMUCL and CLISP, but I'd like to know whether
> I'll get in trouble with other implementations.
This is fairly common and portable use of MAKE-LOAD-FORM.
> Another question: where do I find the set of built-in types that the
> fasdumper is guaranteed to be able to dump?
You find it in section 3.2.4, which you already read :-).
> I've found, to my great dismay, that while CLISP can dump compiled
> functions, CMUCL cannot:
>
> (define-foo *foo* #'list)
> ; Error: Cannot dump objects of type FUNCTION into fasl files.
You can try to use a function of type FUNCALLABLE-STANDARD-OBJECT
instead, and define a MAKE-LOAD-FORM method for it:
(defclass named-function (funcallable-standard-object)
((name :initarg :name))
(:metaclass funcallable-standard-class))
(defmethod shared-initialize :after ((fn named-function) situation &rest more)
(when (or (eq situation 't) (member 'name situation :test #'eq))
(set-funcallable-instance-function fn
(fdefinition (slot-value fn 'name)))))
(defparameter *foo* (make-instance 'named-function :name 'list))
(funcall *foo* 'a 'b 'c) => (A B C)
(defmethod make-load-form ((fn named-function) &optional env)
(make-load-form-saving-slots fn :slot-names '(name) :environment env))
Bruno
> This is fairly common and portable use of MAKE-LOAD-FORM.
Cool. Thanks.
>> Another question: where do I find the set of built-in types that the
>> fasdumper is guaranteed to be able to dump?
> You find it in section 3.2.4, which you already read :-).
Ah, I see. (It's defined as the domain of a partial equivalence relation
-- Lisp humour?)
> You can try to use a function of type FUNCALLABLE-STANDARD-OBJECT
> instead, and define a MAKE-LOAD-FORM method for it:
Unfortunately, I cannot -- the function I'd like to dump is provided
by the user of DEFINE-FOO, and I cannot choose how it's built.
I guess the only solution is to have DEFINE-FOO record the actual
forms that were provided to it, and restrict it to be used in a null
lexical environment. Does anyone see a better solution?
Juliusz