From: Erik Naggum
Subject: Re: writing/printing hash-tables to a file
Date: 
Message-ID: <3108051680098924@naggum.no>
* kp gores
| how do i "print" a hash-table to a file?

  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.
From: Bulent Murtezaoglu
Subject: Re: writing/printing hash-tables to a file
Date: 
Message-ID: <87k961xmcs.fsf@isttest.bogus>
* kp gores 
| how do i "print" a hash-table to a file?
| i want to read the hash-table back from a file later, work
| add/delete entries and then save it back.

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