From: Tunc Simsek
Subject: [#.] more #. problems
Date: 
Message-ID: <38D69EF8.2C160A71@robotics.eecs.berkeley.edu>
Hi,

Although we've discussed #. here before I still have problems.

e.g.
----

(eval-when (load eval compile)
   (defclass test () ()))

(defvar var #.(make-instance 'test))


When I try to compile this fileon CMUCL on Solaris:

 
File: /home/eclair3/varaiya/simsek/tmp/w.lisp
 
In: DEFVAR VAR
  (DEFVAR VAR #<TEST {703172D}>)
--> PROGN UNLESS COND IF IF PROGN 
==>
  (SETQ VAR #<TEST {703172D}>)
Error: (while making load form for #<TEST {703172D}>)
 
Error in function PCL::|(FAST-METHOD NO-APPLICABLE-METHOD (T))|:
   No matching method for the generic-function
#<Standard-Generic-Function MAKE-LOAD-FORM (2) {51D9BE9}>,
when called with arguments (#<TEST {703172D}>
                            #S(C::LEXENV ..))
 
Byte Compiling Top-Level Form: 
 
Compilation unit finished.
  1 error
 


What does this mean, can't we have *constant* objects (I need this for
making matrices).

Thanks,
Tunc

From: Barry Margolin
Subject: Re: [#.] more #. problems
Date: 
Message-ID: <3nxB4.63$SW5.1310@burlma1-snr2>
In article <·················@robotics.eecs.berkeley.edu>,
Tunc Simsek  <······@robotics.eecs.berkeley.edu> wrote:
>Error in function PCL::|(FAST-METHOD NO-APPLICABLE-METHOD (T))|:
>   No matching method for the generic-function
>#<Standard-Generic-Function MAKE-LOAD-FORM (2) {51D9BE9}>,
>when called with arguments (#<TEST {703172D}>
>                            #S(C::LEXENV ..))
> 
>Byte Compiling Top-Level Form: 
> 
>Compilation unit finished.
>  1 error
> 
>
>
>What does this mean, can't we have *constant* objects (I need this for
>making matrices).

In order to dump CLOS instance literals to a file, the class implementor
has to define a MAKE-LOAD-FORM method.  This tells the compiler how to
recreate instances of that class when loading the file.  For many classes
you can probably define a simple method that just calls
MAKE-LOAD-FORM-USING-SLOTS.  See the documentation of these two functions
in the Hyperspec or CLTL2.

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Tim Bradshaw
Subject: Re: [#.] more #. problems
Date: 
Message-ID: <ey3ya7dxo02.fsf@cley.com>
* Tunc Simsek wrote:

> (eval-when (load eval compile)
>    (defclass test () ()))

> (defvar var #.(make-instance 'test))

(I take it your real examples are more complicated than this.)

You need to tell the system how to reconstruct an object of a given
class if it is to be able to dump it into a compiled file, and if it
does not already know how to do that.

You do this by defining a method on MAKE-LOAD-FORM for the class.
given an instance of the class and an optional environment it should
return two values -- a creation form, which will create the object,
and an initialization form which will initialize it.  If the object
appears in the initialization form it will be replaced by the newly
created object when it is evaluated.  Returning only one value is the
same as an initialisation form of NIL.

For this simple case, something like this would do fine:

  (defmethod make-load-form ((object test) &optional env)
    (declare (ignore env))
    `(make-instance (find-class ',(class-name (class-of object)))))

However it is probably better practive to use the provided
MAKE-LOAD-FORM-SAVING-SLOTS function:

  (defmethod make-load-form ((object test) &optional env)
    (make-load-form-saving-slots object :environment env)))

This is all documented in the spec.  You can do more things with
MAKE-LOAD-FORM of course, like run arbitrary code to intern/register
things at load time.

--tim
From: Tunc Simsek
Subject: Re: [#.] more #. problems
Date: 
Message-ID: <38D6B818.8ABC7EB5@robotics.eecs.berkeley.edu>
thanks for all the quick responses.


> (I take it your real examples are more complicated than this.)
>
sure, but not much more complicated, only in that case the class
will have a few slots that have plenty of values assigned to them.

Tunc

Tim Bradshaw wrote:
> 
> * Tunc Simsek wrote:
> 
> > (eval-when (load eval compile)
> >    (defclass test () ()))
> 
> > (defvar var #.(make-instance 'test))
> 
> You need to tell the system how to reconstruct an object of a given
> class if it is to be able to dump it into a compiled file, and if it
> does not already know how to do that.
> 
> You do this by defining a method on MAKE-LOAD-FORM for the class.
> given an instance of the class and an optional environment it should
> return two values -- a creation form, which will create the object,
> and an initialization form which will initialize it.  If the object
> appears in the initialization form it will be replaced by the newly
> created object when it is evaluated.  Returning only one value is the
> same as an initialisation form of NIL.
> 
> For this simple case, something like this would do fine:
> 
>   (defmethod make-load-form ((object test) &optional env)
>     (declare (ignore env))
>     `(make-instance (find-class ',(class-name (class-of object)))))
> 
> However it is probably better practive to use the provided
> MAKE-LOAD-FORM-SAVING-SLOTS function:
> 
>   (defmethod make-load-form ((object test) &optional env)
>     (make-load-form-saving-slots object :environment env)))
> 
> This is all documented in the spec.  You can do more things with
> MAKE-LOAD-FORM of course, like run arbitrary code to intern/register
> things at load time.
> 
> --tim
From: Tim Bradshaw
Subject: Re: [#.] more #. problems
Date: 
Message-ID: <ey3pusoy86w.fsf@cley.com>
* Tunc Simsek wrote:
>> 
> sure, but not much more complicated, only in that case the class
> will have a few slots that have plenty of values assigned to them.

I'm not completely sure why you want to use #. then?  Can't you just
day (defvar x (make-instance ...))?

--tim
From: Tunc Simsek
Subject: Re: [#.] more #. problems
Date: 
Message-ID: <38D7A9F2.93CFDC2F@robotics.eecs.berkeley.edu>
The reason is so I can write and view some matrices as constants.

For example,

(let ((a [1 2, 3 4])
      (b #c(1 2)))

  ....

  (matrix* b a))

etc ...

Here, #c(1 2) is a constant complex number.  Similarily [1 2, 3 4] is
the constant matrix,
which is (in reality) an instance of the class FLOAT-MATRIX.

I hope this makes it clear.

Previously, [1 2 , 3 4] was the expression (make-matrix '(2 2)
:initial-contents '((1 2) (3 4)))
That is, the reader macro returned that code.  Now, I made it so that
the reader macro returns
the matrix itself and not the code and at that point I posted the
question regarding MAKE-LOAD-FORM. (#.)


Regards,
Tunc


Tim Bradshaw wrote:
> 
> * Tunc Simsek wrote:
> >>
> > sure, but not much more complicated, only in that case the class
> > will have a few slots that have plenty of values assigned to them.
> 
> I'm not completely sure why you want to use #. then?  Can't you just
> day (defvar x (make-instance ...))?
> 
> --tim
From: Pierre R. Mai
Subject: Re: [#.] more #. problems
Date: 
Message-ID: <87bt496y6t.fsf@orion.dent.isdn.cs.tu-berlin.de>
Tunc Simsek <······@robotics.eecs.berkeley.edu> writes:

> Hi,
> 
> Although we've discussed #. here before I still have problems.

Your problem is only indirectly connected to #.  The core problem is
externalization of CLOS objects in file compilation.  And the error
message already tells you what you need to do:  Define a method on
make-load-form for test, usually using make-load-form-saving-slots:

(eval-when (load eval compile)
   (defclass test () ())
   (defmethod make-load-form ((inst test) &optional env)
     (make-load-form-saving-slots inst :environment env)))

   (defvar var #.(make-instance 'test))

This should compile and load correctly, producing the intended
result.

-- 
Pierre Mai <····@acm.org>         PGP and GPG keys at your nearest Keyserver
  "One smaller motivation which, in part, stems from altruism is Microsoft-
   bashing." [Microsoft memo, see http://www.opensource.org/halloween1.html]