From: Russell McManus
Subject: Re: Serializing data structures
Date: 
Message-ID: <87d5zl3zzj.fsf@thelonious.dyndns.org>
Gisle S�lensminde <·····@kaktus.ii.uib.no> writes:

> I have a program where I'm working in huge data structures, trees in
> this case. The basic structure looks as follows:
>
> (defstruct tree-node
>    name
>    parent
>    children
>    properties)
>
> The name is the name of the node (string), children is reference to
> the child nodes, while properties is an assoc-list with properties
> of the node or the branch leading to this node. parent is a
> reference to the parent node. These trees can be quite big (up to
> 180,000 leaf nodes). Now I'm creating a core file, and restart that
> (fast) or reread the data from an extarnal format (slow). I would
> like to be able to dump the running data structure and reload it
> into a running lisp session, and not start from a dump/core. (I can
> do that too, but I want to be be able to read the data without
> restarting) This will be much like serializing in java or pickling
> in python.

You can stuff a value into a compiled file and then load the value
again later in a new core.  For user defined types, you have to define
a make-load-form method.

It's actually not that hard.  I spent some time learning about this
incredibly cool feature of CL recently, and saved the test file that I
was playing with.

Try something like this, and read the section of CLHS on
make-load-form.

-russ


(defvar *foo* nil)

(with-open-file (s "/var/tmp/mlf-test-dump.lisp"
		   :direction :output
		   :if-does-not-exist :create
		   :if-exists :supersede)
  (format s "(setf *foo* '#.*foo*)"))

(defun test-value (x)
  (setf *foo* x)
  (format t "~&----------------------~%")
  (format t "~&before compile-file: ~A~%" *foo*)
  (compile-file "/var/tmp/mlf-test-dump")
  (setf *foo* nil)
  (format t "~&after compile-file: ~A~%" *foo*)
  (load "/var/tmp/mlf-test-dump")
  (format t "~&after load: ~A~%" *foo*))

(defclass foo ()
  ((data :initarg :data :reader data)))
(defmethod print-object ((foo foo) s)
  (print-unreadable-object (foo s :type t)
    (format s "~A" (data foo))))
(defmethod make-load-form ((foo foo) &optional environment)
  (make-load-form-saving-slots foo :environment environment))

(test-value (make-instance 'foo :data (list 1 2 3)))
(test-value "abc")
(test-value (list 1 2 3))