This is the mail archive of the guile@cygnus.com mailing list for the guile project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Scheme style auto-resizing hashtable (fwd)


On Wed, 18 Nov 1998, Maciej Stachowiak wrote:

> jglascoe@jay.giss.nasa.gov writes:
> > 
> > 	*** translators: ***
> > 
> > list->hash-table list [wrapper]
> > list->hash-tablev list [wrapper]
> > list->hash-tableq list [wrapper]
> > list->hash-tablex list user-equal? user-hasher [wrapper]
> 
> Can you change these to alist->hash-table*, since they conver
> association lists?

with appropriate "wrapper"s, these functions will work on any list. 

(list->hash-table el (lambda (x) (cons x '())))

> > list->hash-table! list [wrapper]
> > list->hash-tablev! list [wrapper]
> > list->hash-tableq! list [wrapper]
> > list->hash-tablex! list user-equal? user-hasher [wrapper]
> >     Similar to the non-destructive procedures above.
> >     Magically turn list "list" into a hash-table.  Return value
> >     is unspecified.  Note: "list" must be nonempty.
> > 
> 
> Destructive conversion functions are a bad idea and cannot
> generalize. Taking advantage of the fact that a hash table is
> fundamentally a cons cell will make things lose big if you ever change
> your underlying implementation, for instance.

hmm.  I could make them destructive as well as functional.  I mean, "list"
will still be destroyed -- it's finally reduced to (()) -- but rather than
directly converting "list" to a hash-table, the new hash-table will be the
return value of the function.  Would this be preferable to in-place
transformation?  I like the idea, now they'll work fine with empty lists.

Presumably the same comments apply to "hash-table->list!".  If I make that
guy functional (but still destructive) then he'll be able to handle
"empty" hash-tables.

As far as losing big if hash-table objects are not pairs, that's easily
solved with a macro:

(define-syntax imperative-list->hash-table!
  (syntax-rules ()
    ((_ el)
     (set! el (functional-list->hash-table! el)))))

in-place transformation or functional return value... I don't know which
is best.  An *unspecified* return value reminds the user that something
destructive just happened, but then OTOH the "!" at the end of the
procedure also hints at the same thing.

> > hash-table-consume-list! hash-table list [wrapper]
> >     Similar to the non-destructive "hash-table-add-list!" above.
> >     Delete list "list" while inserting (wrapper list-element)
> >     into hash-table "hash-table" for all of "list"'s elements.
> >     Return value is unspecified.
> > 
> 
> I still argue this is useless, especially since Guile is getting a
> generational GC.  Bloating the API unnecessarily is a bad thing.

I don't see how this depends upon the type of GC in use.  Let's say that
"list" has millions of elements.  Surely *any* GC will free much of the
unreferenced cons cells before the procedure is complete.

I agree that the API is a bit big, but all eight of the
"list->hash-table[vqx]?!?" procedures and the
"hash-table-(add|consume)-list!" duo directly call:

static void
basic_hash_table_add_list_x(SCM hash_table, SCM list,
			    SCM user_wrapper, short consume_flag);

And both of "hash-table->list!?" use:

static SCM
basic_hash_table2list(SCM hash_table, SCM user_unwrapper,
                      short consume_flag);

Throwing in the "consume_flag" argument was, I think, both natural and
trivial for both of these basic functions.

In addition to the space-saving virtues of the destructive functions, they
also ensure that the new hash-table or list is the sole owner of the pairs
contained in the old list or hash-table. (assuming nobody else is holding
onto the pairs).


	Jay Glascoe
	jglascoe@jay.giss.nasa.gov