sometimes, it works to print the hash-table object with *PRINT-READABLY*
true. when that fails, you need to make a load-form for the object, and
you might legitimately expect a system to contain something to help you
with that. I found a function EXCL::MAKE-HASH-TABLE-LOAD-FORM in Allegro
CL (for Unix) which appears to offer a reasonable efficiency gain:
CL-USER(37): (let ((table (make-hash-table :test #'equal)))
(setf (gethash "foo" table) "bar")
(setf (gethash "bar" table) "zot")
(excl::make-hash-table-load-form table nil))
(let ((hash-table
(make-hash-table
:test 'equal
:size 103
:rehash-size 1.2
:rehash-threshold 0.6407767)))
(excl::hash-table-fill hash-table #("bar" "zot" "foo" "bar")))
it appears that the other way to handle this, using the FASL read/write
functions in Allegro CL (for Unix), actually produces the exact same
function calls on loading as the above load-form. this probably
shouldn't come as a surprise, but, anyway, here's how to write and read a
hash table to a file with the simplest FASL read/write mechanism:
CL-USER(47): (let ((table (make-hash-table :test #'equal)))
(setf (gethash "foo" table) "bar")
(setf (gethash "bar" table) "zot")
(fasl-write table "/tmp/hash-table.fasl"))
t
CL-USER(48): (fasl-read "/tmp/hash-table.fasl")
(#<equal hash-table with 2 entries @ #x2076ae82>)
if you wish to write more objects to the same file, use FASL-OPEN to get
a FASL stream and write to it, instead:
CL-USER(53): (with-open-stream (fasl (fasl-open "/tmp/hash-table.fasl"))
(let ((table (make-hash-table :test #'equal)))
(setf (gethash "foo" table) "bar")
(setf (gethash "bar" table) "zot")
(fasl-write table fasl)
(fasl-write table fasl)))
t
CL-USER(54): (fasl-read "/tmp/hash-table.fasl")
(#<equal hash-table with 2 entries @ #x20799e2a>
#<equal hash-table with 2 entries @ #x2079a4d2>)
| i want to read the hash-table back from a file later, work with it,
| add/delete entries and then save it back.
this sounds more like you actually want a "hash table" to reside on disk
and have a mapping onto a simple file-based database. or in other words,
persistent objects.
neither printable/loadable hash tables nor persistent objects are fully
portable features in Common Lisp, i.e., you will need to use functions
specific to the implementation in _some_ way. other Common Lisps offer
other ways than Allegro CL, but the above is at least how I do it.
#:Erik
--
http://www.naggum.no/spam.html is about my spam protection scheme and how
to guarantee that you reach me. in brief: if you reply to a news article
of mine, be sure to include an In-Reply-To or References header with the
message-ID of that message in it. otherwise, you need to read that page.
I think Erik's suggestion is good in that it illustrates how you can
work with a specific CL to do that you want. The simple obvious
solution, of course, is to dump all the data items in the hash table
to a file individually and readably along with the count of items.
You can then read re-hash into a freshly created hash table of
suitable size the next time you start your lisp. This is not very
efficient but trivial to implement and portable. It might just do what
you need if the file i/o only happens when you kill and re-start your
lisp session.
If the hash table is truly huge, you might still want to do some
implementation specific stuff to the garbage collector to minimize the
the scanning of what you know to be persistent data.
BM