Subject: Re: writing/printing hash-tables to a file
From: Erik Naggum <clerik@naggum.no>
Date: 1998/06/28
Newsgroups: comp.lang.lisp
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.