From: Vladimir V. Zolotych
Subject: Saving/restoring hash tables
Date: 
Message-ID: <3AF517D2.3B40BA96@eurocom.od.ua>
Hello

I need to save/restore contents of the hash table.
Key of the hash is FIXNUM, value is the instance of
the simple class ACCOUNT-HISTORY.

(defclass account-history ()
  ((id :initarg :account-history-id :initform 0 
     :accessor account-history-id)
   (login :initarg :account-history-login :initform nil 
     :accessor account-history-login)
   (credit :initarg :account-history-credit :initform 0 
     :accessor account-history-credit)
   (values :initarg :account-history-values :initform nil 
     :accessor account-history-values)))

Which way such savings should be done? I've write the following
save/load functions.

(defun save-state (output-file)
  (with-open-file (output-stream output-file :direction :output :if-exists :supersede)
    (loop for id being the hash-key of *accounts* using (hash-value x)
          do (let ((*print-right-margin* nil))
;; I've inserted *PRINT-RIGHT-MARGIN* here in hope
;; to get #.(make-instance ...) as one line in resulted file.
;; This doesn't has any effect.
;; Pretty-printer alings velue for ~S in one column because lines
;; are too long. 
               (format
                output-stream
;; Sorry for very long line, I didn't found yet 
;; how to write them nicely.

                "~&#.(make-instance 'account-history :account-history-id ~D :account-history-login ~S
:account-history-credit (float ~F) :account-history-values (mapcar #'float '~S))~%"
                id
                (account-history-login x)
                (account-history-credit x)
                (account-history-values x))))))

(defun load-state (input-file &optional (accounts (make-hash-table)))
  (with-open-file (input-stream input-file)
    (loop for x = (read input-stream nil nil) while x
          do (setf (gethash (account-history-id x) accounts) x)))
  accounts)

Is this acceptable, or may be such savings can be done in
a shortest way?

-- 
Vladimir Zolotych                         ······@eurocom.od.ua

From: Jeff Greif
Subject: Re: Saving/restoring hash tables
Date: 
Message-ID: <61nK6.17841$154.5490016@typhoon.we.rr.com>
Have you investigated make-load-form as a way to organize your code for
this?
Jeff

"Vladimir V. Zolotych" <······@eurocom.od.ua> wrote in message
······················@eurocom.od.ua...
> Hello
>
> I need to save/restore contents of the hash table.
> Key of the hash is FIXNUM, value is the instance of
> the simple class ACCOUNT-HISTORY.
From: Vladimir V. Zolotych
Subject: Re: Saving/restoring hash tables
Date: 
Message-ID: <3AFA8268.E3816511@eurocom.od.ua>
Jeff Greif wrote:
> 
> Have you investigated make-load-form as a way to organize your code for
> this?

For a class

(defclass account-history ()
  ((id :initarg :account-history-id :initform 0 
      :accessor account-history-id)
   (login :initarg :account-history-login :initform nil 
      :accessor account-history-login)
   (credit :initarg :account-history-credit :initform 0 
      :accessor account-history-credit)
   (values :initarg :account-history-values :initform nil 
      :accessor account-history-values)))

and particular instance of it I see in CMUCL.

0] (describe *temp*)
#<ACCOUNT-HISTORY {4804C375}> is an instance of class #<Standard-Class ACCOUNT-HISTORY {480295ED}>:
 The following slots have :INSTANCE allocation:
 VALUES    (0.353441 0.353441)
 CREDIT    -5.186725
 LOGIN     "venger"
 ID        2437
0] (make-load-form-saving-slots *temp* :slot-names '(id login credit values))
Warning:  :SLOT-NAMES MAKE-LOAD-FORM option not implemented, dumping all slots:
  #<ACCOUNT-HISTORY {4804C375}>
:JUST-DUMP-IT-NORMALLY
0] 

What does it mean ':JUST-DUMP-IT-NORMALLY' ?

In Allegro I see

G-USER(727): (make-load-form-saving-slots *temp*)
(ALLOCATE-INSTANCE (FIND-CLASS 'ACCOUNT-HISTORY))
(SETF (SLOT-VALUE #<ACCOUNT-HISTORY @ #x20ea7cc2> 'VALUES) '(0.353441 0.353441)
      (SLOT-VALUE #<ACCOUNT-HISTORY @ #x20ea7cc2> 'CREDIT) '-5.186725
      (SLOT-VALUE #<ACCOUNT-HISTORY @ #x20ea7cc2> 'LOGIN) '"venger"
      (SLOT-VALUE #<ACCOUNT-HISTORY @ #x20ea7cc2> 'ID) '2437)

CLHS says that MAKE-LOAD-FORM-SAVING-SLOTS 
"Returns forms that, when evaluated, ....". 
I need some education on that. How things like #<...> 
could be evaluated ?

-- 
Vladimir Zolotych                         ······@eurocom.od.ua
From: Kent M Pitman
Subject: Re: Saving/restoring hash tables
Date: 
Message-ID: <sfwk83ptd5d.fsf@world.std.com>
"Vladimir V. Zolotych" <······@eurocom.od.ua> writes:

> In Allegro I see
> 
> G-USER(727): (make-load-form-saving-slots *temp*)
> (ALLOCATE-INSTANCE (FIND-CLASS 'ACCOUNT-HISTORY))
> (SETF (SLOT-VALUE #<ACCOUNT-HISTORY @ #x20ea7cc2> 'VALUES) '(0.353441 0.353441)
>       (SLOT-VALUE #<ACCOUNT-HISTORY @ #x20ea7cc2> 'CREDIT) '-5.186725
>       (SLOT-VALUE #<ACCOUNT-HISTORY @ #x20ea7cc2> 'LOGIN) '"venger"
>       (SLOT-VALUE #<ACCOUNT-HISTORY @ #x20ea7cc2> 'ID) '2437)
> 
> CLHS says that MAKE-LOAD-FORM-SAVING-SLOTS 
> "Returns forms that, when evaluated, ....". 
> I need some education on that. How things like #<...> 
> could be evaluated ?

Evaluation is an operation on objects, not on printed representations.
Objects that are not symbols or lists will self-evaluate.

Self-evaluating objects that cannot be printed re-readably can,
nevertheless, be dumped *if* there is a MAKE-LOAD-FORM method on them.
It will describe how to dump the data.

Curiously, because f this, a clever PRINT-OBJECT method could create
a printed representation other than #<...> if it wanted to, by calling
the MAKE-LOAD-FORM operation and constructing an appropriate #. expression
(assuming *READ-EVAL* isn't disbled) but sometimes
programs will print as #<..> not because there isn't a re-readable 
representation, but because it's more compact or less circular or whatever,
... or because identity is important and because making a new account-history
object should only be attempted from another image.
From: Pierre R. Mai
Subject: Re: Saving/restoring hash tables
Date: 
Message-ID: <877kzp1aa5.fsf@orion.bln.pmsf.de>
"Vladimir V. Zolotych" <······@eurocom.od.ua> writes:

> 0] (describe *temp*)
> #<ACCOUNT-HISTORY {4804C375}> is an instance of class #<Standard-Class ACCOUNT-HISTORY {480295ED}>:
>  The following slots have :INSTANCE allocation:
>  VALUES    (0.353441 0.353441)
>  CREDIT    -5.186725
>  LOGIN     "venger"
>  ID        2437
> 0] (make-load-form-saving-slots *temp* :slot-names '(id login credit values))
> Warning:  :SLOT-NAMES MAKE-LOAD-FORM option not implemented, dumping all slots:
>   #<ACCOUNT-HISTORY {4804C375}>
> :JUST-DUMP-IT-NORMALLY
> 0] 
> 
> What does it mean ':JUST-DUMP-IT-NORMALLY' ?

It is a CMU CL internal optimization, which is recognized by the fasl
dumper, which then goes on to dump the instance using internal
mechanisms.  Don't know how standard compliant that is, though...

> In Allegro I see
> 
> G-USER(727): (make-load-form-saving-slots *temp*)
> (ALLOCATE-INSTANCE (FIND-CLASS 'ACCOUNT-HISTORY))
> (SETF (SLOT-VALUE #<ACCOUNT-HISTORY @ #x20ea7cc2> 'VALUES) '(0.353441 0.353441)
>       (SLOT-VALUE #<ACCOUNT-HISTORY @ #x20ea7cc2> 'CREDIT) '-5.186725
>       (SLOT-VALUE #<ACCOUNT-HISTORY @ #x20ea7cc2> 'LOGIN) '"venger"
>       (SLOT-VALUE #<ACCOUNT-HISTORY @ #x20ea7cc2> 'ID) '2437)
> 
> CLHS says that MAKE-LOAD-FORM-SAVING-SLOTS 
> "Returns forms that, when evaluated, ....". 
> I need some education on that. How things like #<...> 
> could be evaluated ?

They aren't (at least in this case).  If you read the entry for
make-load-form(-saving-slots), you will see that all occurrences of
the instance being saved are specially recognized in those forms, and
will be replaced by the implementation at loadtime with the newly
created instance, i.e. the one returned by the forms of the first
value.  I.e. at load-time the following will happen:

(ALLOCATE-INSTANCE (FIND-CLASS 'ACCOUNT-HISTORY))

is evaluated, and all occurrences of the old instance (which by now
probably is only a marker) #<ACCOUNT-HISTORY @ #x20ea7cc2> in the
second form are replaced with the result of the above form, and then
the second form is evaluated, i.e. 

(SETF (SLOT-VALUE #<the new instance here> 'VALUES) '(0.353441 0.353441)
      (SLOT-VALUE #<the new instance here> 'CREDIT) '-5.186725
      (SLOT-VALUE #<the new instance here> 'LOGIN) '"venger"
      (SLOT-VALUE #<the new instance here> 'ID) '2437)

Thereby setting up the new instance...

The whole make-load-form stuff is a bit tricky to explain and
understand at first, but once you grok it, it's not that bad.

Regs, Pierre.

-- 
Pierre R. Mai <····@acm.org>                    http://www.pmsf.de/pmai/
 The most likely way for the world to be destroyed, most experts agree,
 is by accident. That's where we come in; we're computer professionals.
 We cause accidents.                           -- Nathaniel Borenstein
From: Vladimir V. Zolotych
Subject: Re: Saving/restoring hash tables
Date: 
Message-ID: <3AFBA85B.155C06D1@eurocom.od.ua>
"Pierre R. Mai" wrote:

Thanks to you and Kent as well.

> The whole make-load-form stuff is a bit tricky to explain and
> understand at first, but once you grok it, it's not that bad.

I've arrived at a conclusion that among other applicable
ways to do what I needed using MAKE-LOAD-FORM will not be
on the first place.

-- 
Vladimir Zolotych                         ······@eurocom.od.ua