unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Re: print hash table to disk and reread in hash table
       [not found]           ` <mailman.17897.1220021571.18990.help-gnu-emacs@gnu.org>
@ 2008-08-29 18:10             ` Ted Zlatanov
  2008-08-30  5:18               ` tomas
  0 siblings, 1 reply; 86+ messages in thread
From: Ted Zlatanov @ 2008-08-29 18:10 UTC (permalink / raw)
  To: help-gnu-emacs; +Cc: Emacs Development

On Fri, 29 Aug 2008 17:52:07 +0300 Eli Zaretskii <eliz@gnu.org> wrote: 

EZ> You mean, like bindat.el?
>> 
>> That looks useful for binary data.  I don't see from the code how to use
>> it to save and load a hashtable.

EZ> I never used it, I just advertised the closest hit for what you seemed
EZ> to be looking.

>> In addition, this library doesn't manage file I/O.  I'd expect the
>> library do do content coding and error handling internally.  This is,
>> actually, the most tedious part.

EZ> A cause for a small project, I guess. ;-)

I can just copy the code out of gnus-registry.el and abstract the
functionality to do a first cut of such a library.  For a large
hashtable, though, converting to a list on the way in and out is
inefficient compared to storing it in a more "native" format.  Is there
such a format, comparable to the native list read-eval format, as seen
in gnus-load:

  (with-temp-buffer
    (insert-file-contents file)
    (while (not (eobp))
      (condition-case type
	  (let ((form (read (current-buffer))))
	    (eval form))
;; ... much code omitted ...

cc to emacs-devel as I think this is of interest to that list.

Thanks
Ted


^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: print hash table to disk and reread in hash table
  2008-08-29 18:10             ` print hash table to disk and reread in hash table Ted Zlatanov
@ 2008-08-30  5:18               ` tomas
  2008-08-30  9:17                 ` Ted Zlatanov
  0 siblings, 1 reply; 86+ messages in thread
From: tomas @ 2008-08-30  5:18 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: Emacs Development

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Fri, Aug 29, 2008 at 01:10:11PM -0500, Ted Zlatanov wrote:
> The following message is a courtesy copy of an article
> that has been posted to gnu.emacs.help as well.
> 
> On Fri, 29 Aug 2008 17:52:07 +0300 Eli Zaretskii <eliz@gnu.org> wrote: 
> 
> EZ> You mean, like bindat.el?
> >> 
> >> That looks useful for binary data.  I don't see from the code how to use
> >> it to save and load a hashtable.

I don't know the context -- but I have been musing on and off about a
persistent hash (backed by something like GDBM), similar to what Perl
offers.

Regards
- -- tomás
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)

iD8DBQFIuNgPBcgs9XrR2kYRAoxsAJ99r4ARwpnX1GQgaoX08E2iy86M8wCfUV4t
C81sI7b0SZFrOD6GkBw3Nb4=
=0/DR
-----END PGP SIGNATURE-----




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: print hash table to disk and reread in hash table
  2008-08-30  5:18               ` tomas
@ 2008-08-30  9:17                 ` Ted Zlatanov
  2008-08-30 12:03                   ` tomas
  2008-11-17 17:15                   ` Ted Zlatanov
  0 siblings, 2 replies; 86+ messages in thread
From: Ted Zlatanov @ 2008-08-30  9:17 UTC (permalink / raw)
  To: emacs-devel

On Sat, 30 Aug 2008 07:18:07 +0200 tomas@tuxteam.de wrote: 

t> On Fri, Aug 29, 2008 at 01:10:11PM -0500, Ted Zlatanov wrote:
>> The following message is a courtesy copy of an article
>> that has been posted to gnu.emacs.help as well.
>> 
>> On Fri, 29 Aug 2008 17:52:07 +0300 Eli Zaretskii <eliz@gnu.org> wrote: 
>> 
EZ> You mean, like bindat.el?
>> >> 
>> >> That looks useful for binary data.  I don't see from the code how to use
>> >> it to save and load a hashtable.

t> I don't know the context -- but I have been musing on and off about a
t> persistent hash (backed by something like GDBM), similar to what Perl
t> offers.

I was trying to serialize a hashtable to a file, and there's no good way
other than converting it to a list or making a file of (puthash)
statements.  bindat.el seems OK but doesn't seem to have a hashtable
spec in the format.

Persistent storage is useful and could easily be implemented with a
small sqlite database file.  It could be an option when creating a
hashtable.  It doesn't solve serialization, though.  The file is not
human-readable, which is the advantage of formats like the Gnus newsrc
file.  So it's not what I'm looking for, but still an useful addition to
Emacs IMO :)

Ted





^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: print hash table to disk and reread in hash table
  2008-08-30  9:17                 ` Ted Zlatanov
@ 2008-08-30 12:03                   ` tomas
  2008-11-17 17:15                   ` Ted Zlatanov
  1 sibling, 0 replies; 86+ messages in thread
From: tomas @ 2008-08-30 12:03 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Sat, Aug 30, 2008 at 04:17:54AM -0500, Ted Zlatanov wrote:
> On Sat, 30 Aug 2008 07:18:07 +0200 tomas@tuxteam.de wrote: 

> Persistent storage is useful and could easily be implemented with a
> small sqlite database file.  It could be an option when creating a
> hashtable.  It doesn't solve serialization, though.  The file is not
> human-readable, which is the advantage of formats like the Gnus newsrc
> file.  So it's not what I'm looking for, but still an useful addition to
> Emacs IMO :)

Ah, I see. Thanks for the clarification.

Regards
- -- tomás
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)

iD8DBQFIuTcHBcgs9XrR2kYRAtsUAJ95yoYMkIrCd0nmRihuTqVWqRrf4wCfU8CR
xW6I0HjK770iWnI9Q+HxPD8=
=HkLJ
-----END PGP SIGNATURE-----




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: print hash table to disk and reread in hash table
  2008-08-30  9:17                 ` Ted Zlatanov
  2008-08-30 12:03                   ` tomas
@ 2008-11-17 17:15                   ` Ted Zlatanov
  2008-11-19 21:37                     ` hash-table-{to, from}-alist (was: print hash table to disk and reread in hash table) Ted Zlatanov
  1 sibling, 1 reply; 86+ messages in thread
From: Ted Zlatanov @ 2008-11-17 17:15 UTC (permalink / raw)
  To: emacs-devel

On Sat, 30 Aug 2008 04:17:54 -0500 Ted Zlatanov <tzz@lifelogs.com> wrote: 

TZ> I was trying to serialize a hashtable to a file, and there's no good way
TZ> other than converting it to a list or making a file of (puthash)
TZ> statements.  bindat.el seems OK but doesn't seem to have a hashtable
TZ> spec in the format.

Steve Yegge published Ejacs over the weekend, which included some (IMHO
very reasonable) complaints about Emacs Lisp's lack of hashtable
serialization.

I propose the following functions (originals were contributed to Gnus by
Andreas Fuchs <asf@void.at>):

(defun hash-table-to-alist (hash)
  "Build an alist from the values in HASH."
  (let ((list nil))
    (maphash
     (lambda (key value)
       (setq list (cons (cons key value) list)))
     hash)
    list))

;; this would take the usual make-hash-table arguments (:test, :size,
;; :rehash-size, :rehash-threshold, :weakness) so those don't have to
;; get serialized with the alist.  This makes the implementation much
;; simpler, complicating life slightly for the API consumers

;; untested

(defun hash-table-from-alist (alist &rest options)
  "Build a hashtable from the values in ALIST."
  (let ((ht (apply 'make-hash-table options)))
    (mapc
     (lambda (kv-pair)
       (puthash (car kv-pair) (cdr kv-pair) ht))
     alist)
     ht))

Implemented in C these would probably be a bit faster.  They are pretty
trivial, but in the Emacs core they would provide a universal way to
serialize hashtables.  IMO this is better than trying to serialize the
hashtable directly, since there are so many ways to read and write lists
in Emacs Lisp, while hashtable support for the same will require a lot
of effort, new APIs, and little real gain.

Ted





^ permalink raw reply	[flat|nested] 86+ messages in thread

* hash-table-{to, from}-alist (was: print hash table to disk and reread in hash table)
  2008-11-17 17:15                   ` Ted Zlatanov
@ 2008-11-19 21:37                     ` Ted Zlatanov
  2008-11-19 21:57                       ` hash-table-{to, from}-alist Glenn Morris
  2008-11-21 22:02                       ` Stefan Monnier
  0 siblings, 2 replies; 86+ messages in thread
From: Ted Zlatanov @ 2008-11-19 21:37 UTC (permalink / raw)
  To: emacs-devel

On Mon, 17 Nov 2008 11:15:46 -0600 Ted Zlatanov <tzz@lifelogs.com> wrote: 

...
TZ> I propose the following functions (originals were contributed to Gnus by
TZ> Andreas Fuchs <asf@void.at>):

TZ> (defun hash-table-to-alist (hash)
TZ>   "Build an alist from the values in HASH."
TZ>   (let ((list nil))
TZ>     (maphash
TZ>      (lambda (key value)
TZ>        (setq list (cons (cons key value) list)))
TZ>      hash)
TZ>     list))

TZ> ;; this would take the usual make-hash-table arguments (:test, :size,
TZ> ;; :rehash-size, :rehash-threshold, :weakness) so those don't have to
TZ> ;; get serialized with the alist.  This makes the implementation much
TZ> ;; simpler, complicating life slightly for the API consumers

TZ> ;; untested

TZ> (defun hash-table-from-alist (alist &rest options)
TZ>   "Build a hashtable from the values in ALIST."
TZ>   (let ((ht (apply 'make-hash-table options)))
TZ>     (mapc
TZ>      (lambda (kv-pair)
TZ>        (puthash (car kv-pair) (cdr kv-pair) ht))
TZ>      alist)
TZ>      ht))

Even though the functions here are not by any means perfect (for
instance, a hashtable containing another hashtable will not be converted
correctly) I think they should go into Emacs.  No one has commented yet.

I can address the nested hashtable problem by recursion, but it won't
work when converting back into a hashtable because I won't know if the
original data was a hashtable or an alist.  Please let me know if
there's a better way that preserves the clean hashtable-to-alist
mapping (maybe I have to include metadata, after all, which I was hoping
to avoid).

If there are no objections or comments, I'll commit my version tomorrow
with a manual update to follow once the functions are stable.  Where
should this go under the lisp/ directory?

Thanks
Ted





^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-11-19 21:37                     ` hash-table-{to, from}-alist (was: print hash table to disk and reread in hash table) Ted Zlatanov
@ 2008-11-19 21:57                       ` Glenn Morris
  2008-11-20 19:07                         ` Ted Zlatanov
  2008-11-21 22:02                       ` Stefan Monnier
  1 sibling, 1 reply; 86+ messages in thread
From: Glenn Morris @ 2008-11-19 21:57 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

Ted Zlatanov wrote:

> If there are no objections or comments, I'll commit my version tomorrow

There is supposed to be a feature freeze, hence I would think you need
an explicit OK install new features. (I have no comments on the code.)




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-11-19 21:57                       ` hash-table-{to, from}-alist Glenn Morris
@ 2008-11-20 19:07                         ` Ted Zlatanov
  0 siblings, 0 replies; 86+ messages in thread
From: Ted Zlatanov @ 2008-11-20 19:07 UTC (permalink / raw)
  To: emacs-devel

On Wed, 19 Nov 2008 16:57:24 -0500 Glenn Morris <rgm@gnu.org> wrote: 

GM> Ted Zlatanov wrote:
>> If there are no objections or comments, I'll commit my version tomorrow

GM> There is supposed to be a feature freeze, hence I would think you need
GM> an explicit OK install new features. (I have no comments on the code.)

Ah, I was not thinking (nothing unusual :)

I'll wait until after the feature freeze, unless Chong or Stefan fall in
love with my suggestion and want to push it in.  Thank you.

Ted





^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-11-19 21:37                     ` hash-table-{to, from}-alist (was: print hash table to disk and reread in hash table) Ted Zlatanov
  2008-11-19 21:57                       ` hash-table-{to, from}-alist Glenn Morris
@ 2008-11-21 22:02                       ` Stefan Monnier
  2008-11-21 22:22                         ` Ted Zlatanov
  1 sibling, 1 reply; 86+ messages in thread
From: Stefan Monnier @ 2008-11-21 22:02 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

TZ> I propose the following functions (originals were contributed to Gnus by
TZ> Andreas Fuchs <asf@void.at>):

TZ> (defun hash-table-to-alist (hash)
TZ> (defun hash-table-from-alist (alist &rest options)

> If there are no objections or comments, I'll commit my version tomorrow
> with a manual update to follow once the functions are stable.  Where
> should this go under the lisp/ directory?

They don't look too harmful, but I think we need more: we need to hook
this into prin1 and into read so it works transparently.

So all this looks pretty "post 23.1" to me.


        Stefan




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-11-21 22:02                       ` Stefan Monnier
@ 2008-11-21 22:22                         ` Ted Zlatanov
  2008-11-22  3:18                           ` Stefan Monnier
  0 siblings, 1 reply; 86+ messages in thread
From: Ted Zlatanov @ 2008-11-21 22:22 UTC (permalink / raw)
  To: emacs-devel

On Fri, 21 Nov 2008 17:02:06 -0500 Stefan Monnier <monnier@iro.umontreal.ca> wrote: 

TZ> I propose the following functions (originals were contributed to Gnus by
TZ> Andreas Fuchs <asf@void.at>):

TZ> (defun hash-table-to-alist (hash)
TZ> (defun hash-table-from-alist (alist &rest options)

>> If there are no objections or comments, I'll commit my version tomorrow
>> with a manual update to follow once the functions are stable.  Where
>> should this go under the lisp/ directory?

SM> They don't look too harmful, but I think we need more: we need to hook
SM> this into prin1 and into read so it works transparently.

We can't, because we're converting to an alist and there's no way to
convert back.  True serialization would require a new marker, similar to
() for lists and [] for vectors.  Braces would probably work, I don't
think they are used anywhere:

{ :prop1 prop-value1 :prop2 prop-value2 ... key1 val1 key2 val2 ... }

(:prop1 is :test for example)

WDYT?  It would cause read errors to have an odd number of elements, but
otherwise it's pretty clean.  The properties are the same as those you
can pass to make-hash-table, and are always serialized (but not required
on read).  You can have keys named :test for example, because the :test
property happens first and then any subsequent :test keys are assumed to
be hash keys.

Incidentally, the docs for prin1 should probably have examples for the
output of a vector and a series of simple examples of the other data
types, or a link to somewhere those are shown.  I didn't find it in the
manual.

SM> So all this looks pretty "post 23.1" to me.

OK.  If we agree on the format I can produce a patch for eventual
inclusion.

Ted





^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-11-21 22:22                         ` Ted Zlatanov
@ 2008-11-22  3:18                           ` Stefan Monnier
  2008-11-22  5:45                             ` tomas
                                               ` (2 more replies)
  0 siblings, 3 replies; 86+ messages in thread
From: Stefan Monnier @ 2008-11-22  3:18 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

SM> They don't look too harmful, but I think we need more: we need to hook
SM> this into prin1 and into read so it works transparently.

> We can't, because we're converting to an alist and there's no way to
> convert back.  True serialization would require a new marker, similar to
> () for lists and [] for vectors.  Braces would probably work, I don't
> think they are used anywhere:

> { :prop1 prop-value1 :prop2 prop-value2 ... key1 val1 key2 val2 ... }

> (:prop1 is :test for example)

I was thinking of something more like #<hash-table ...> where "..."
would contain the props and then the key/value pairs.  I.e. an extension
of the current (un`read'able syntax).


        Stefan




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-11-22  3:18                           ` Stefan Monnier
@ 2008-11-22  5:45                             ` tomas
  2008-11-22 12:27                               ` Stephen J. Turnbull
  2008-11-22  6:07                             ` Miles Bader
  2008-11-22 18:57                             ` Ted Zlatanov
  2 siblings, 1 reply; 86+ messages in thread
From: tomas @ 2008-11-22  5:45 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Ted Zlatanov, emacs-devel

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Fri, Nov 21, 2008 at 10:18:41PM -0500, Stefan Monnier wrote:
[...]
> I was thinking of something more like #<hash-table ...> where "..."
> would contain the props and then the key/value pairs.  I.e. an extension
> of the current (un`read'able syntax).

I like this one more: it is more extensible (not that lots of extensions
will spring up, but at least the syntax is not in the way if someday...
you know).

Regards
- -- tomás
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)

iD8DBQFJJ5xmBcgs9XrR2kYRAkZuAJ90ZOToHHIXZSfOJFDYMc/jNQd9SACeN/vY
ZbGq/mzgxgKTfnHeY/WZV+I=
=NUG/
-----END PGP SIGNATURE-----




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-11-22  3:18                           ` Stefan Monnier
  2008-11-22  5:45                             ` tomas
@ 2008-11-22  6:07                             ` Miles Bader
  2008-11-22 15:27                               ` tomas
  2008-11-22 18:57                             ` Ted Zlatanov
  2 siblings, 1 reply; 86+ messages in thread
From: Miles Bader @ 2008-11-22  6:07 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Ted Zlatanov, emacs-devel

Stefan Monnier <monnier@iro.umontreal.ca> writes:
> I was thinking of something more like #<hash-table ...> where "..."
> would contain the props and then the key/value pairs.  I.e. an extension
> of the current (un`read'able syntax).

Isn't there a general lisp convention that all syntaxes of the form
#<...> are output-only, not intended to be readable?

-Miles

-- 
History, n. An account mostly false, of events mostly unimportant, which are
brought about by rulers mostly knaves, and soldiers mostly fools.




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-11-22  5:45                             ` tomas
@ 2008-11-22 12:27                               ` Stephen J. Turnbull
  2008-11-22 15:21                                 ` tomas
  0 siblings, 1 reply; 86+ messages in thread
From: Stephen J. Turnbull @ 2008-11-22 12:27 UTC (permalink / raw)
  To: tomas; +Cc: Ted Zlatanov, Stefan Monnier, emacs-devel

tomas@tuxteam.de writes:

 > On Fri, Nov 21, 2008 at 10:18:41PM -0500, Stefan Monnier wrote:
 > [...]
 > > I was thinking of something more like #<hash-table ...> where "..."
 > > would contain the props and then the key/value pairs.  I.e. an extension
 > > of the current (un`read'able syntax).
 > 
 > I like this one more: it is more extensible (not that lots of extensions
 > will spring up, but at least the syntax is not in the way if someday...
 > you know).

I'm not sure what's wrong with

        (let ((tbl (make-hash-table ...)))
          (puthash key1 val1 tbl)
          ...)

as a read syntax for hash tables.

N.B. XEmacs and SXEmacs already have lots of object types.  If you're
going to start proliferating `read'able print syntaxes, starting with
an extensible one would be nice.




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-11-22 12:27                               ` Stephen J. Turnbull
@ 2008-11-22 15:21                                 ` tomas
  2008-11-22 17:38                                   ` Stephen J. Turnbull
  0 siblings, 1 reply; 86+ messages in thread
From: tomas @ 2008-11-22 15:21 UTC (permalink / raw)
  To: Stephen J. Turnbull; +Cc: Ted Zlatanov, tomas, Stefan Monnier, emacs-devel

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Sat, Nov 22, 2008 at 09:27:18PM +0900, Stephen J. Turnbull wrote:
> tomas@tuxteam.de writes:
> 
>  > On Fri, Nov 21, 2008 at 10:18:41PM -0500, Stefan Monnier wrote:
>  > [...]
>  > > I was thinking of something more like #<hash-table ...> where
>  > > "..."

[...]

>  > I like this one more: it is more extensible [...]

[...]

> I'm not sure what's wrong with
>
>         (let ((tbl (make-hash-table ...)))
>           (puthash key1 val1 tbl)
>           ...)
>
> as a read syntax for hash tables.

Hm. Abstraction? Separate "how it's spelt" from "how it's done"?

Not that I think it has much weight. Make-hash-table is an abstraction
itself, after all. I couldn't decide between both variants.

Regards
- -- tomás




>  > 
>  > I like this one more: it is more extensible (not that lots of extensions
>  > will spring up, but at least the syntax is not in the way if someday...
>  > you know).
> 
> I'm not sure what's wrong with
> 
>         (let ((tbl (make-hash-table ...)))
>           (puthash key1 val1 tbl)
>           ...)
> 
> as a read syntax for hash tables.
> 
> N.B. XEmacs and SXEmacs already have lots of object types.  If you're
> going to start proliferating `read'able print syntaxes, starting with
> an extensible one would be nice.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)

iD8DBQFJKCN2Bcgs9XrR2kYRAncCAJ48gH/pAj1pwGYC30ib8tif2YqLFQCeLitk
YgVNDIKOihglmb+j7a8PAec=
=oX27
-----END PGP SIGNATURE-----




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-11-22  6:07                             ` Miles Bader
@ 2008-11-22 15:27                               ` tomas
  0 siblings, 0 replies; 86+ messages in thread
From: tomas @ 2008-11-22 15:27 UTC (permalink / raw)
  To: Miles Bader; +Cc: Ted Zlatanov, Stefan Monnier, emacs-devel

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Sat, Nov 22, 2008 at 03:07:04PM +0900, Miles Bader wrote:
> Stefan Monnier <monnier@iro.umontreal.ca> writes:
> > I was thinking of something more like #<hash-table ...> where "..."
> > would contain the props and then the key/value pairs.  I.e. an extension
> > of the current (un`read'able syntax).
> 
> Isn't there a general lisp convention that all syntaxes of the form
> #<...> are output-only, not intended to be readable?

Right -- that would be one point more iin favour of Stephen's proposal
upthread. More lispy, it seems.

Regards
- -- tomás
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)

iD8DBQFJKCTeBcgs9XrR2kYRAo1oAJ41PEmsRrp5XH9GZrfs/nWOV3VjzQCfVtT3
s8tTYe9RU5M2UqtaBWeGZWE=
=I5NL
-----END PGP SIGNATURE-----




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-11-22 15:21                                 ` tomas
@ 2008-11-22 17:38                                   ` Stephen J. Turnbull
  2008-11-24 15:44                                     ` Richard M Stallman
  0 siblings, 1 reply; 86+ messages in thread
From: Stephen J. Turnbull @ 2008-11-22 17:38 UTC (permalink / raw)
  To: tomas; +Cc: Ted Zlatanov, Stefan Monnier, emacs-devel

tomas@tuxteam.de writes:

 > >  > On Fri, Nov 21, 2008 at 10:18:41PM -0500, Stefan Monnier wrote:
 > >  > [...]
 > >  > > I was thinking of something more like #<hash-table ...> where
 > >  > > "..."

BTW, it turns out that in XEmacs and its descendants prin1 uses the CL
structure syntax when `print-readably' is bound to t:

    #s(hash-table size 1 data (x x-value))

This is not guaranteed to actually be acceptable to the reader, since
some contained objects may not be printable (eg, improper lists).
However, since most types in XEmacs do have readable print
representations, it does correctly recurse on composite types like
hash tables (as long as the expression is a tree; DAGs will contain
copies, cycles will be elided, etc).





^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-11-22  3:18                           ` Stefan Monnier
  2008-11-22  5:45                             ` tomas
  2008-11-22  6:07                             ` Miles Bader
@ 2008-11-22 18:57                             ` Ted Zlatanov
  2 siblings, 0 replies; 86+ messages in thread
From: Ted Zlatanov @ 2008-11-22 18:57 UTC (permalink / raw)
  To: emacs-devel

On Fri, 21 Nov 2008 22:18:41 -0500 Stefan Monnier <monnier@iro.umontreal.ca> wrote: 

Ted Zlatanov wrote:
>> { :prop1 prop-value1 :prop2 prop-value2 ... key1 val1 key2 val2 ... }

>> (:prop1 is :test for example)

SM> I was thinking of something more like #<hash-table ...> where "..."
SM> would contain the props and then the key/value pairs.  I.e. an extension
SM> of the current (un`read'able syntax).

Why would you want to make it unreadable if (as above, and in the other
proposals) you can make it readable?  The whole point of this discussion
was serializing hash tables; pretty-printing them is trivial.

On Sat, 22 Nov 2008 21:27:18 +0900 "Stephen J. Turnbull" <stephen@xemacs.org> wrote: 

SJT> I'm not sure what's wrong with

SJT>         (let ((tbl (make-hash-table ...)))
SJT>           (puthash key1 val1 tbl)
SJT>           ...)

SJT> as a read syntax for hash tables.

It's verbose, and doesn't follow what vectors do (they use [] instead of
(make-vector ...), setting some precedent for special read syntax).
OTOH it's readable, extensible, and easy to set up your way.

SJT> N.B. XEmacs and SXEmacs already have lots of object types.  If you're
SJT> going to start proliferating `read'able print syntaxes, starting with
SJT> an extensible one would be nice.

I only want some format that lets me easily print and read back a hash
table; the actual syntax is not important to me.  My proposal was only a
suggestion.

On Sun, 23 Nov 2008 02:38:59 +0900 "Stephen J. Turnbull" <stephen@xemacs.org> wrote: 

SJT> BTW, it turns out that in XEmacs and its descendants prin1 uses the CL
SJT> structure syntax when `print-readably' is bound to t:

SJT>     #s(hash-table size 1 data (x x-value))

SJT> This is not guaranteed to actually be acceptable to the reader, since
SJT> some contained objects may not be printable (eg, improper lists).
SJT> However, since most types in XEmacs do have readable print
SJT> representations, it does correctly recurse on composite types like
SJT> hash tables (as long as the expression is a tree; DAGs will contain
SJT> copies, cycles will be elided, etc).

That's fine too, and it would make sense to use something that has been
proven to work already.  As I said, the syntax doesn't matter to me.
Whatever the Emacs maintainers and developers like is OK, it just has to
work :)

Ted





^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-11-22 17:38                                   ` Stephen J. Turnbull
@ 2008-11-24 15:44                                     ` Richard M Stallman
  2008-11-24 16:58                                       ` Stefan Monnier
  2008-11-24 17:21                                       ` Ted Zlatanov
  0 siblings, 2 replies; 86+ messages in thread
From: Richard M Stallman @ 2008-11-24 15:44 UTC (permalink / raw)
  To: Stephen J. Turnbull; +Cc: tzz, tomas, monnier, emacs-devel

    BTW, it turns out that in XEmacs and its descendants prin1 uses the CL
    structure syntax when `print-readably' is bound to t:

	#s(hash-table size 1 data (x x-value))

Being compatible with that seems like a good idea,
if there is no obstacle.




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-11-24 15:44                                     ` Richard M Stallman
@ 2008-11-24 16:58                                       ` Stefan Monnier
  2008-11-24 17:21                                       ` Ted Zlatanov
  1 sibling, 0 replies; 86+ messages in thread
From: Stefan Monnier @ 2008-11-24 16:58 UTC (permalink / raw)
  To: rms; +Cc: Stephen J. Turnbull, tomas, tzz, emacs-devel

>     BTW, it turns out that in XEmacs and its descendants prin1 uses the CL
>     structure syntax when `print-readably' is bound to t:

> 	#s(hash-table size 1 data (x x-value))

> Being compatible with that seems like a good idea,
> if there is no obstacle.

Indeed.


        Stefan




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-11-24 15:44                                     ` Richard M Stallman
  2008-11-24 16:58                                       ` Stefan Monnier
@ 2008-11-24 17:21                                       ` Ted Zlatanov
  2008-11-25  1:50                                         ` Stephen J. Turnbull
  2008-11-25  2:57                                         ` Stefan Monnier
  1 sibling, 2 replies; 86+ messages in thread
From: Ted Zlatanov @ 2008-11-24 17:21 UTC (permalink / raw)
  To: emacs-devel

On Mon, 24 Nov 2008 10:44:44 -0500 Richard M Stallman <rms@gnu.org> wrote: 

RMS>     BTW, it turns out that in XEmacs and its descendants prin1 uses the CL
RMS>     structure syntax when `print-readably' is bound to t:

RMS> 	#s(hash-table size 1 data (x x-value))

RMS> Being compatible with that seems like a good idea,
RMS> if there is no obstacle.

The equality test is necessary if it was given originally (meaning, if
it's not 'eql).  I don't think we should ever omit it, even if it's the
default value, for readability.

The :weakness, :rehash-size, and :rehash-threshold options to
make-hash-table, can probably be omitted when they are the defaults.

Would this work?

#s(hash-table size 2 test equal data (k1 v1) (k2 v2))

Finally, the size is just a hint with make-hash-table; should the (read)
allow wrong sizes or throw an error?

Thanks
Ted





^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-11-24 17:21                                       ` Ted Zlatanov
@ 2008-11-25  1:50                                         ` Stephen J. Turnbull
  2008-11-25 17:33                                           ` Ted Zlatanov
  2008-11-25  2:57                                         ` Stefan Monnier
  1 sibling, 1 reply; 86+ messages in thread
From: Stephen J. Turnbull @ 2008-11-25  1:50 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

Ted Zlatanov writes:

 > The equality test is necessary if it was given originally (meaning,
 > if it's not 'eql).  I don't think we should ever omit it, even if
 > it's the default value, for readability.

I disagree.  But it's not incompatible as long as you don't make the
:test option to make-hash-table obligatory. ;-)

 > Would this work?
 > 
 > #s(hash-table size 2 test equal data (k1 v1) (k2 v2))

Not quite.  The data field in XEmacs is a plist, and the construct
above signals an error.

#s(hash-table size 2 test equal data (k1 v1 k2 v2))

 > Finally, the size is just a hint with make-hash-table; should the (read)
 > allow wrong sizes or throw an error?

XEmacs allows wrong sizes.  I think this makes sense, but it probably
isn't deliberate (the structure-reading mechanism validates field
values one at a time; I don't see a provision for cross-field
consistency checks).

#s(hash-table size 10 data (y y-value x x-value))
#<hash-table size 2/29 data (y y-value x x-value) 0x587cb2e2>





^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-11-24 17:21                                       ` Ted Zlatanov
  2008-11-25  1:50                                         ` Stephen J. Turnbull
@ 2008-11-25  2:57                                         ` Stefan Monnier
  2008-11-25  7:02                                           ` Stephen J. Turnbull
  1 sibling, 1 reply; 86+ messages in thread
From: Stefan Monnier @ 2008-11-25  2:57 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

RMS> #s(hash-table size 1 data (x x-value))

RMS> Being compatible with that seems like a good idea,
RMS> if there is no obstacle.

> The equality test is necessary if it was given originally (meaning, if
> it's not 'eql).  I don't think we should ever omit it, even if it's the
> default value, for readability.

I don't see any reason to treat this specially, actually.

> The :weakness, :rehash-size, and :rehash-threshold options to
> make-hash-table, can probably be omitted when they are the defaults.

Indeed.

> Would this work?
> #s(hash-table size 2 test equal data (k1 v1) (k2 v2))
> Finally, the size is just a hint with make-hash-table; should the (read)
> allow wrong sizes or throw an error?

I don't know what "size" is meant to represent in XEmacs's or CL's use
of this representation.  Is it the expected average number of elements
in the table?  or the expected max number of elements?  or the current
number of elements?


        Stefan




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-11-25  2:57                                         ` Stefan Monnier
@ 2008-11-25  7:02                                           ` Stephen J. Turnbull
  0 siblings, 0 replies; 86+ messages in thread
From: Stephen J. Turnbull @ 2008-11-25  7:02 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Ted Zlatanov, emacs-devel

Stefan Monnier writes:

 > I don't know what "size" is meant to represent in XEmacs's or CL's use
 > of this representation.  Is it the expected average number of elements
 > in the table?  or the expected max number of elements?  or the current
 > number of elements?

Size is the actual number of elements currently in the table.  In
XEmacs, weak elements that are "no longer there" are not guaranteed to
be removed from the table at any particular time, and I suspect size
is ambiguous for weak tables.  Ask Mike Sperber (XEmacs.org mailbox
"mike") and/or Martin Buchholz ("martin") if you want to know the
details and the design.

In the XEmacs implementation, the parameters of #s(hash-table ...) are
simply passed to make-hash-table, so as Ted says, it's just a hint.





^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-11-25  1:50                                         ` Stephen J. Turnbull
@ 2008-11-25 17:33                                           ` Ted Zlatanov
  2008-11-25 23:50                                             ` Ted Zlatanov
  2008-11-26  2:29                                             ` Stephen J. Turnbull
  0 siblings, 2 replies; 86+ messages in thread
From: Ted Zlatanov @ 2008-11-25 17:33 UTC (permalink / raw)
  To: emacs-devel

On Tue, 25 Nov 2008 10:50:53 +0900 "Stephen J. Turnbull" <stephen@xemacs.org> wrote: 

SJT> Ted Zlatanov writes:
>> The equality test is necessary if it was given originally (meaning,
>> if it's not 'eql).  I don't think we should ever omit it, even if
>> it's the default value, for readability.

SJT> I disagree.  But it's not incompatible as long as you don't make the
SJT> :test option to make-hash-table obligatory. ;-)

OK, I'll make :test optional.  Is size mandatory?  I ask since you put
it in your example, but you could have done so to illustrate
parameters.

>> Would this work?
>> 
>> #s(hash-table size 2 test equal data (k1 v1) (k2 v2))

SJT> Not quite.  The data field in XEmacs is a plist, and the construct
SJT> above signals an error.

SJT> #s(hash-table size 2 test equal data (k1 v1 k2 v2))

I'm OK with that format and it seems pretty good, since (read) can (I
think) reuse the plist read syntax for the contents, so there's not much
work for a simple implementation.  Of course, an optimized
implementation might be necessary, but a working simple solution is
always a good first step.

>> Finally, the size is just a hint with make-hash-table; should the (read)
>> allow wrong sizes or throw an error?

SJT> XEmacs allows wrong sizes.  I think this makes sense, but it probably
SJT> isn't deliberate (the structure-reading mechanism validates field
SJT> values one at a time; I don't see a provision for cross-field
SJT> consistency checks).

SJT> #s(hash-table size 10 data (y y-value x x-value))
SJT> #<hash-table size 2/29 data (y y-value x x-value) 0x587cb2e2>

That's fine.  I'll just hard-code the size to 42 then. (kidding)

Ted





^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-11-25 17:33                                           ` Ted Zlatanov
@ 2008-11-25 23:50                                             ` Ted Zlatanov
  2008-11-26  1:46                                               ` Stefan Monnier
  2008-11-26  2:29                                             ` Stephen J. Turnbull
  1 sibling, 1 reply; 86+ messages in thread
From: Ted Zlatanov @ 2008-11-25 23:50 UTC (permalink / raw)
  To: emacs-devel

Here's a patch to print.c to implement printing out a hashtable's
properties and content as discussed.  I *think* I'm doing it right based
on what I see elsewhere in print.c and fns.c.  I rely on print_object to
do the work.  I know the indentation is off, sorry.

This patch does:

(let ((h (make-hash-table :rehash-size 20.0 :rehash-threshold 0.001 :weakness 'key))) 
  (puthash 1 2 h) 
  (puthash 5 'env h) 
  (print h))

--> #<hash-table 'eql key 2/65 0x83c49a0>

        #s<hash-table size 65 test 'eql weak 'key rehash-size 20.0 rehash-threshold 0.001 data (1 2 5 env )>

I know it's broken for circular references (e.g. (puthash 6 h h)
above).  How should I handle that?

The new output is offset and printed after the old-style output as a
sanity check.  Let me know if the code is OK and I'll make it the only
output of printing a hashtable, clean it up (based on any comments I get
and the TODO items), and go on to writing the read code.  I won't commit
it of course, just keep it as a patch until the trunk is open again.

Thanks
Ted

Index: print.c
===================================================================
RCS file: /sources/emacs/emacs/src/print.c,v
retrieving revision 1.253
diff -c -r1.253 print.c
*** print.c	31 Jul 2008 05:33:53 -0000	1.253
--- print.c	25 Nov 2008 23:40:54 -0000
***************
*** 2052,2057 ****
--- 2052,2108 ----
  	  sprintf (buf, " 0x%lx", (unsigned long) h);
  	  strout (buf, -1, -1, printcharfun, 0);
  	  PRINTCHAR ('>');
+ 
+ /*
+   implement a readable output:
+   #s(hash-table size 2 test equal data (k1 v1 k2 v2))
+ */
+           /* always print the size */
+           sprintf (buf, "\n\n\t#s<hash-table size %ld", (long) XVECTOR (h->next)->size);
+           strout (buf, -1, -1, printcharfun, 0);
+ 
+ 	  if (SYMBOLP (h->test))
+ 	    {
+               strout (" test '", -1, -1, printcharfun, 0);
+               print_object (h->test, printcharfun, 0);
+             }
+ 
+ 	  if (SYMBOLP (h->weak) && ! NILP(h->weak))
+ 	    {
+               strout (" weak '", -1, -1, printcharfun, 0);
+               print_object (h->weak, printcharfun, 0);
+             }
+ 
+ 	  if (FLOATP (h->rehash_size) || INTEGERP (h->rehash_size))
+ 	    {
+               strout (" rehash-size ", -1, -1, printcharfun, 0);
+               print_object (h->rehash_size, printcharfun, 0);
+             }
+ 
+           /* the rehash threshold must be 0 < threshold < 1 so it's never an integer */
+ 	  if (FLOATP (h->rehash_threshold))
+ 	    {
+               strout (" rehash-threshold ", -1, -1, printcharfun, 0);
+               print_object (h->rehash_threshold, printcharfun, 0);
+             }
+ 
+           strout (" data ", -1, -1, printcharfun, 0);
+ 
+           /* print the data here as a plist */
+           int i;
+ 
+           PRINTCHAR ('(');
+           for (i = 0; i < HASH_TABLE_SIZE (h); ++i)
+             if (!NILP (HASH_HASH (h, i)))
+               {
+                 print_object (HASH_KEY (h, i), printcharfun, 0);
+                 PRINTCHAR (' ');
+                 print_object (HASH_VALUE (h, i), printcharfun, 0);
+                 PRINTCHAR (' '); /* TODO: should not be printed at end */
+               }
+           PRINTCHAR (')');
+ 	  PRINTCHAR ('>');
+ 
  	}
        else if (BUFFERP (obj))
  	{





^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-11-25 23:50                                             ` Ted Zlatanov
@ 2008-11-26  1:46                                               ` Stefan Monnier
  2008-11-26  2:16                                                 ` David De La Harpe Golden
  0 siblings, 1 reply; 86+ messages in thread
From: Stefan Monnier @ 2008-11-26  1:46 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

>         #s<hash-table size 65 test 'eql weak 'key rehash-size 20.0 rehash-threshold 0.001 data (1 2 5 env )>

Looks OK, except I don't think it's a good idea to include ' in front of
key and eql.  I know it's what we do right now, but in order to read it
back in, it's going to be more trouble.  Also I'd generally prefer using
":weakness" rather than "weak", so it's as close as possible to the key
args passed to make-hash-table.

> I know it's broken for circular references (e.g. (puthash 6 h h)
> above).  How should I handle that?

The same way as the other circularities.  I.e. it should mostly "just
work", except you'll have to change the code that does the first pass so
that it doesn't skip hash tables.

> + 	  if (SYMBOLP (h->test))
> + 	    {
> +               strout (" test '", -1, -1, printcharfun, 0);
> +               print_object (h->test, printcharfun, 0);
> +             }

Shouldn't it be !NILP (h->test) rather than SYMBOLP (h->test)?

> + 	  if (SYMBOLP (h->weak) && ! NILP(h->weak))
> + 	    {
> +               strout (" weak '", -1, -1, printcharfun, 0);
> +               print_object (h->weak, printcharfun, 0);
> +             }

Here as well, !NILP should be sufficient.

> + 	  if (FLOATP (h->rehash_size) || INTEGERP (h->rehash_size))
> + 	    {
> +               strout (" rehash-size ", -1, -1, printcharfun, 0);
> +               print_object (h->rehash_size, printcharfun, 0);
> +             }

And again !NILP sounds preferable.

Otherwise, it looks OK,


        Stefan




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-11-26  1:46                                               ` Stefan Monnier
@ 2008-11-26  2:16                                                 ` David De La Harpe Golden
  2008-11-26  3:48                                                   ` Stefan Monnier
  0 siblings, 1 reply; 86+ messages in thread
From: David De La Harpe Golden @ 2008-11-26  2:16 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Ted Zlatanov, emacs-devel

Stefan Monnier wrote:
>>         #s<hash-table size 65 test 'eql weak 'key rehash-size 20.0 rehash-threshold 0.001 data (1 2 5 env )>
> 
> Looks OK, except I don't think it's a good idea to include ' in front of
> key and eql.  I know it's what we do right now, but in order to read it
> back in, it's going to be more trouble.  Also I'd generally prefer using
> ":weakness" rather than "weak", so it's as close as possible to the key
> args passed to make-hash-table.
>

The #s kind of bothers me.  In common lisp, #s(a ...) is readable - as 
an instance of struct a [*]. Hence the "s". Now, hashtables may well use 
a struct for their metadata as an implementation detail, but the #s<...> 
does look to me like an odd mix of commmon lisp #s(...) 
struct-instance-literal syntax and #<...> 
printable-but-unreadable-object syntax.

I realise that for emacs lisp compatibility with common lisp is a 
nongoal and compatibility with xemacs lisp is of some interest, so it's 
not a huge argument against #s<...>,  I'm just saying I'm finding it a 
bit confusing coming from CL (mind you, CL anyway lacks any print/read
roundtripping hashtable syntax)

[*]
CL-USER> (defstruct a b c)
A
CL-USER> (make-a :b 1 :c 2)
#S(A :B 1 :C 2)
CL-USER> #s(a :b 2 :c 3)
#S(A :B 2 :C 3)
CL-USER>





^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-11-25 17:33                                           ` Ted Zlatanov
  2008-11-25 23:50                                             ` Ted Zlatanov
@ 2008-11-26  2:29                                             ` Stephen J. Turnbull
  2008-11-26  3:34                                               ` David De La Harpe Golden
  2008-11-26 16:06                                               ` Ted Zlatanov
  1 sibling, 2 replies; 86+ messages in thread
From: Stephen J. Turnbull @ 2008-11-26  2:29 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

Ted Zlatanov writes:
 > On Tue, 25 Nov 2008 10:50:53 +0900 "Stephen J. Turnbull" <stephen@xemacs.org> wrote: 
 > 
 > SJT> Ted Zlatanov writes:
 > >> The equality test is necessary if it was given originally (meaning,
 > >> if it's not 'eql).  I don't think we should ever omit it, even if
 > >> it's the default value, for readability.
 > 
 > SJT> I disagree.  But it's not incompatible as long as you don't make the
 > SJT> :test option to make-hash-table obligatory. ;-)
 > 
 > OK, I'll make :test optional.  Is size mandatory?  I ask since you put
 > it in your example, but you could have done so to illustrate
 > parameters.

It's not mandatory in the read syntax, but an accurate estimate will
avoid some consing at read time.  As an implementation detail, the
write syntax does include it if non-zero.

#s(hash-table)
--> #<hash-table size 0/29 0x5fa328ee>
(let ((print-readably t))
  (prin1 #s(hash-table)))
#s(hash-table)
--> #<hash-table size 0/29 0x5fa4b2ef>
#s(hash-table size 2)
--> #<hash-table size 0/29 0x5fa56456>
(let ((print-readably t))
  (prin1 #s(hash-table size 2)))
#s(hash-table)
--> #<hash-table size 0/29 0x5fa5a16d>

 > I'm OK with that format and it seems pretty good,

Good.  I would be very annoyed if we had to support an alternative
syntax.




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-11-26  2:29                                             ` Stephen J. Turnbull
@ 2008-11-26  3:34                                               ` David De La Harpe Golden
  2008-11-26 16:06                                               ` Ted Zlatanov
  1 sibling, 0 replies; 86+ messages in thread
From: David De La Harpe Golden @ 2008-11-26  3:34 UTC (permalink / raw)
  To: Stephen J. Turnbull; +Cc: Ted Zlatanov, emacs-devel

Stephen J. Turnbull wrote:

>  > I'm OK with that format and it seems pretty good,
> 
> Good.  I would be very annoyed if we had to support an alternative
> syntax.

[I think I misunderstood xemacs in my last post, not a user of it], so:

"#s(hash-table ...)" with round brackets or
"#s<hash-table ...>" with angle brackets ?

Checking xemacs lisp ref and thread posts, looks like round brackets are 
consistent with xemacs. Not that it's a major change, just that Ted's
patch used <>  (I realise now that all participants in the thread before 
I chimed in cluelessly may simply have taken it as understood that would 
be changed later, sorry...)






































^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-11-26  2:16                                                 ` David De La Harpe Golden
@ 2008-11-26  3:48                                                   ` Stefan Monnier
  2008-11-26  5:46                                                     ` David De La Harpe Golden
  0 siblings, 1 reply; 86+ messages in thread
From: Stefan Monnier @ 2008-11-26  3:48 UTC (permalink / raw)
  To: David De La Harpe Golden; +Cc: Ted Zlatanov, emacs-devel

> The #s kind of bothers me.  In common lisp, #s(a ...) is readable - as an
> instance of struct a [*]. Hence the "s". Now, hashtables may well use
> a struct for their metadata as an implementation detail, but the #s<...>
> does look to me like an odd mix of commmon lisp #s(...)
> struct-instance-literal syntax and #<...>
> printable-but-unreadable-object syntax.

For what it's worth:

   % clisp
     i i i i i i i       ooooo    o        ooooooo   ooooo   ooooo
     I I I I I I I      8     8   8           8     8     o  8    8
     I  \ `+' /  I      8         8           8     8        8    8
      \  `-+-'  /       8         8           8      ooooo   8oooo
       `-__|__-'        8         8           8           8  8
           |            8     o   8           8     o     8  8
     ------+------       ooooo    8oooooo  ooo8ooo   ooooo   8
   
   Welcome to GNU CLISP 2.44.1 (2008-02-23) <http://clisp.cons.org/>
   
   Copyright (c) Bruno Haible, Michael Stoll 1992, 1993
   Copyright (c) Bruno Haible, Marcus Daniels 1994-1997
   Copyright (c) Bruno Haible, Pierpaolo Bernardi, Sam Steingold 1998
   Copyright (c) Bruno Haible, Sam Steingold 1999-2000
   Copyright (c) Sam Steingold, Bruno Haible 2001-2008
   
   Type :h and hit Enter for context help.
   
   [1]> (let ((x (make-hash-table))) (setf (gethash 4 x) 6) x)
   #S(HASH-TABLE :TEST FASTHASH-EQL (4 . 6))
   [2]> 

So the question is should we use #s(...) as CL does, or #s<...> as
XEmacs does.


        Stefan




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-11-26  3:48                                                   ` Stefan Monnier
@ 2008-11-26  5:46                                                     ` David De La Harpe Golden
  0 siblings, 0 replies; 86+ messages in thread
From: David De La Harpe Golden @ 2008-11-26  5:46 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Ted Zlatanov, emacs-devel

Stefan Monnier wrote:

 > So the question is should we use #s(...) as CL does,

(That's definitely implementation-specific, just what clisp in 
particular does)

> or #s<...> as XEmacs does.
> 

N.B. It's actually #s(...) in XEmacs too, at least when variable 
print-readably is t. Otherwise the not-readable #<...> (no "s") is used, 
as per Stephen J. Turnbull's posts to this thread, also shown in [1]

Since hashtables are typically used for largish numbers of keys, 
supporting such an XEmacs-like print-readably variable* and suppressing 
the output of key/value data (at least beyond a certain key count) for 
the non-readable #<...> case seems like it might be quite desirable, 
though I dunno if XEmacs actually does such suppression, CL
implementations tend to (regarding xemacs compat it can't matter much 
since it's only the non-readable case).

* itself similar to CL *print-readably*, though  there's no guarantee a 
particular CL implementation can actually print its hashtables readably 
no matter how you twiddle that. Clisp does its thing. SBCL spits out a 
#. read-time evaluation lump that constructs a hashtable. Clozure CL (at 
least the outdated version on my system) signals a print-not-readable 
error... [2]

[1] http://www.xemacs.org/Documentation/21.5/html/lispref_9.html#SEC67
[2] http://www.lispworks.com/documentation/HyperSpec/Body/v_pr_rda.htm




















^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-11-26  2:29                                             ` Stephen J. Turnbull
  2008-11-26  3:34                                               ` David De La Harpe Golden
@ 2008-11-26 16:06                                               ` Ted Zlatanov
  2008-11-26 18:10                                                 ` Stefan Monnier
  2008-11-26 19:44                                                 ` Davis Herring
  1 sibling, 2 replies; 86+ messages in thread
From: Ted Zlatanov @ 2008-11-26 16:06 UTC (permalink / raw)
  To: emacs-devel

On Wed, 26 Nov 2008 11:29:06 +0900 "Stephen J. Turnbull" <stephen@xemacs.org> wrote: 

SJT> Ted Zlatanov writes:
>> OK, I'll make :test optional.  Is size mandatory?  I ask since you put
>> it in your example, but you could have done so to illustrate
>> parameters.

SJT> It's not mandatory in the read syntax, but an accurate estimate will
SJT> avoid some consing at read time.  As an implementation detail, the
SJT> write syntax does include it if non-zero.

Since it doesn't matter, I'll leave it in even if zero.  I think it
improves legibility at the cost of 7 bytes.

SJT> Good.  I would be very annoyed if we had to support an alternative
SJT> syntax.

Right, my goal here is to find the simplest solution that works for
everyone.  I changed it to #s(hash-table ...) as discussed.

On Tue, 25 Nov 2008 20:46:23 -0500 Stefan Monnier <monnier@iro.umontreal.ca> wrote: 

>> #s<hash-table size 65 test 'eql weak 'key rehash-size 20.0 rehash-threshold 0.001 data (1 2 5 env )>

SM> Looks OK, except I don't think it's a good idea to include ' in front of
SM> key and eql.  I know it's what we do right now, but in order to read it
SM> back in, it's going to be more trouble.  Also I'd generally prefer using
SM> ":weakness" rather than "weak", so it's as close as possible to the key
SM> args passed to make-hash-table.

OK, both done.

>> I know it's broken for circular references (e.g. (puthash 6 h h)
>> above).  How should I handle that?

SM> The same way as the other circularities.  I.e. it should mostly
SM> "just work", except you'll have to change the code that does the
SM> first pass so that it doesn't skip hash tables.

Sorry, I don't know what you mean.  My iterator doesn't skip hash
tables, does it?  Or are you discussing something else?

SM> Shouldn't it be !NILP (h->test) rather than SYMBOLP (h->test)?
SM> Here as well [weakness], !NILP should be sufficient.
SM> And again [rehash_size and rehash_threshold] !NILP sounds preferable.

All done.

On Wed, 26 Nov 2008 05:46:32 +0000 David De La Harpe Golden <david@harpegolden.net> wrote: 

DDLHG> N.B. It's actually #s(...) in XEmacs too, at least when variable
DDLHG> print-readably is t. Otherwise the not-readable #<...> (no "s") is
DDLHG> used, as per Stephen J. Turnbull's posts to this thread, also shown in
DDLHG> [1]

I am still printing the two versions of the object in the attached
patch, but I can of course make it conditional on print-readably.  IMHO
hashtables should always be printed completely and should be treated
like lists and vectors.  If, however, compatibility with XEmacs is
desired or people feel strongly for print-readably, I will implement
with print-readably.

It prints an extra space at the end, which I still have as a simple
TODO.  I also have to handle circular references, but otherwise it seems
pretty reasonable.

Ted

Index: print.c
===================================================================
RCS file: /sources/emacs/emacs/src/print.c,v
retrieving revision 1.253
diff -c -r1.253 print.c
*** print.c	31 Jul 2008 05:33:53 -0000	1.253
--- print.c	26 Nov 2008 16:01:57 -0000
***************
*** 2052,2057 ****
--- 2052,2107 ----
  	  sprintf (buf, " 0x%lx", (unsigned long) h);
  	  strout (buf, -1, -1, printcharfun, 0);
  	  PRINTCHAR ('>');
+ 
+ /*
+   implement a readable output, e.g.:
+   #s(hash-table size 2 test equal data (k1 v1 k2 v2))
+ */
+           /* always print the size */
+           sprintf (buf, "\n\n\t#s(hash-table size %ld", (long) XVECTOR (h->next)->size);
+           strout (buf, -1, -1, printcharfun, 0);
+ 
+ 	  if (!NILP(h->test))
+ 	    {
+               strout (" test ", -1, -1, printcharfun, 0);
+               print_object (h->test, printcharfun, 0);
+             }
+ 
+ 	  if (!NILP(h->weak))
+ 	    {
+               strout (" weakness ", -1, -1, printcharfun, 0);
+               print_object (h->weak, printcharfun, 0);
+             }
+ 
+ 	  if (!NILP(h->rehash_size))
+ 	    {
+               strout (" rehash-size ", -1, -1, printcharfun, 0);
+               print_object (h->rehash_size, printcharfun, 0);
+             }
+ 
+ 	  if (!NILP(h->rehash_threshold))
+ 	    {
+               strout (" rehash-threshold ", -1, -1, printcharfun, 0);
+               print_object (h->rehash_threshold, printcharfun, 0);
+             }
+ 
+           strout (" data ", -1, -1, printcharfun, 0);
+ 
+           /* print the data here as a plist */
+           int i;
+ 
+           PRINTCHAR ('(');
+           for (i = 0; i < HASH_TABLE_SIZE (h); ++i)
+             if (!NILP (HASH_HASH (h, i)))
+               {
+                 print_object (HASH_KEY (h, i), printcharfun, 0);
+                 PRINTCHAR (' ');
+                 print_object (HASH_VALUE (h, i), printcharfun, 0);
+                 PRINTCHAR (' '); /* TODO: should not be printed at end */
+               }
+           PRINTCHAR (')');
+ 	  PRINTCHAR (')');
+ 
  	}
        else if (BUFFERP (obj))
  	{





^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-11-26 16:06                                               ` Ted Zlatanov
@ 2008-11-26 18:10                                                 ` Stefan Monnier
  2008-11-26 20:37                                                   ` Ted Zlatanov
  2008-11-26 19:44                                                 ` Davis Herring
  1 sibling, 1 reply; 86+ messages in thread
From: Stefan Monnier @ 2008-11-26 18:10 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

> everyone.  I changed it to #s(hash-table ...) as discussed.

Good, thanks.

SM> The same way as the other circularities.  I.e. it should mostly
SM> "just work", except you'll have to change the code that does the
SM> first pass so that it doesn't skip hash tables.
> Sorry, I don't know what you mean.  My iterator doesn't skip hash
> tables, does it?  Or are you discussing something else?

The print code does 2 passes over the data: a first one to collect the
set of objects it's going to print, and a second to do the actual print.
This 2-pass approach is done to handle cycles and sharing (so that when
an object appears several times in the output, we know it right when we
print the first occurrence).  IIUC your patch only patches the second
pass, but not the first.

> IMHO hashtables should always be printed completely and should be
> treated like lists and vectors.  If, however, compatibility with
> XEmacs is desired or people feel strongly for print-readably, I will
> implement with print-readably.

char tables are always printed in full and we haven't had any complaints
about that, so you're probably right: let's just always print them
in full.  If it turns out to be problematic in some cases, we can later
on add some extra variable to control the level of detail.


        Stefan




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-11-26 16:06                                               ` Ted Zlatanov
  2008-11-26 18:10                                                 ` Stefan Monnier
@ 2008-11-26 19:44                                                 ` Davis Herring
  2008-11-26 20:41                                                   ` Ted Zlatanov
  1 sibling, 1 reply; 86+ messages in thread
From: Davis Herring @ 2008-11-26 19:44 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

> It prints an extra space at the end, which I still have as a simple
> TODO.  I also have to handle circular references, but otherwise it seems
> pretty reasonable.

I don't mean to assume that it's news to you, but if it happens to be,
it's quite easy to fix this:

int printed=0;
for(...) {
  if(print_this_one) {
    if(printed) PRINTCHAR(' ');
    printed=1;
    print_it();
    /* no trailing space here */
  }
}

Move declaration to block beginning, adjust coding style, and salt to taste.

Davis

-- 
This product is sold by volume, not by mass.  If it appears too dense or
too sparse, it is because mass-energy conversion has occurred during
shipping.




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-11-26 18:10                                                 ` Stefan Monnier
@ 2008-11-26 20:37                                                   ` Ted Zlatanov
  2008-11-26 21:16                                                     ` Ted Zlatanov
  2008-11-27  0:24                                                     ` Stephen J. Turnbull
  0 siblings, 2 replies; 86+ messages in thread
From: Ted Zlatanov @ 2008-11-26 20:37 UTC (permalink / raw)
  To: emacs-devel

On Wed, 26 Nov 2008 13:10:38 -0500 Stefan Monnier <monnier@iro.umontreal.ca> wrote: 

SM> The same way as the other circularities.  I.e. it should mostly
SM> "just work", except you'll have to change the code that does the
SM> first pass so that it doesn't skip hash tables.
>> Sorry, I don't know what you mean.  My iterator doesn't skip hash
>> tables, does it?  Or are you discussing something else?

SM> The print code does 2 passes over the data: a first one to collect the
SM> set of objects it's going to print, and a second to do the actual print.
SM> This 2-pass approach is done to handle cycles and sharing (so that when
SM> an object appears several times in the output, we know it right when we
SM> print the first occurrence).  IIUC your patch only patches the second
SM> pass, but not the first.

I'll research this, thanks for explaining.

>> IMHO hashtables should always be printed completely and should be
>> treated like lists and vectors.  If, however, compatibility with
>> XEmacs is desired or people feel strongly for print-readably, I will
>> implement with print-readably.

SM> char tables are always printed in full and we haven't had any complaints
SM> about that, so you're probably right: let's just always print them
SM> in full.  If it turns out to be problematic in some cases, we can later
SM> on add some extra variable to control the level of detail.

Great.  Maybe XEmacs should add print-unreadably ;)

Ted





^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-11-26 19:44                                                 ` Davis Herring
@ 2008-11-26 20:41                                                   ` Ted Zlatanov
  0 siblings, 0 replies; 86+ messages in thread
From: Ted Zlatanov @ 2008-11-26 20:41 UTC (permalink / raw)
  To: emacs-devel

On Wed, 26 Nov 2008 11:44:32 -0800 (PST) "Davis Herring" <herring@lanl.gov> wrote: 

>> It prints an extra space at the end, which I still have as a simple
>> TODO.  I also have to handle circular references, but otherwise it seems
>> pretty reasonable.

DH> I don't mean to assume that it's news to you, but if it happens to be,
DH> it's quite easy to fix this:

DH> int printed=0;
DH> for(...) {
DH>   if(print_this_one) {
DH>     if(printed) PRINTCHAR(' ');
DH>     printed=1;
DH>     print_it();
DH>     /* no trailing space here */
DH>   }
DH> }

DH> Move declaration to block beginning, adjust coding style, and salt to taste.

Thanks, I used your suggestion.  I'll post the updated patch once I get
circular references cleared up.

Ted





^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-11-26 20:37                                                   ` Ted Zlatanov
@ 2008-11-26 21:16                                                     ` Ted Zlatanov
  2008-12-01 22:01                                                       ` Ted Zlatanov
  2008-11-27  0:24                                                     ` Stephen J. Turnbull
  1 sibling, 1 reply; 86+ messages in thread
From: Ted Zlatanov @ 2008-11-26 21:16 UTC (permalink / raw)
  To: emacs-devel

On Wed, 26 Nov 2008 14:37:28 -0600 Ted Zlatanov <tzz@lifelogs.com> wrote: 

TZ> On Wed, 26 Nov 2008 13:10:38 -0500 Stefan Monnier <monnier@iro.umontreal.ca> wrote: 
SM> The print code does 2 passes over the data: a first one to collect the
SM> set of objects it's going to print, and a second to do the actual print.
SM> This 2-pass approach is done to handle cycles and sharing (so that when
SM> an object appears several times in the output, we know it right when we
SM> print the first occurrence).  IIUC your patch only patches the second
SM> pass, but not the first.

TZ> I'll research this, thanks for explaining.

The patch below does all the previously discussed formatting plus
detection of circular references and Davis Herring's suggestion of
skipping the first preliminary space.  The old-style hashtable printout
is disabled with an #ifdef, so only the new style is available.

I tested it quite a bit, especially with compound data members, and it
seems to work all right.  If this patch is OK (Stefan, please make the
call since you've been looking at it) I'll go on to the reading code.

Thanks
Ted

Index: print.c
===================================================================
RCS file: /sources/emacs/emacs/src/print.c,v
retrieving revision 1.253
diff -c -r1.253 print.c
*** print.c	31 Jul 2008 05:33:53 -0000	1.253
--- print.c	26 Nov 2008 21:15:18 -0000
***************
*** 1341,1346 ****
--- 1341,1347 ----
   loop:
    if (STRINGP (obj) || CONSP (obj) || VECTORP (obj)
        || COMPILEDP (obj) || CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj)
+       || HASH_TABLE_P (obj)
        || (! NILP (Vprint_gensym)
  	  && SYMBOLP (obj)
  	  && !SYMBOL_INTERNED_P (obj)))
***************
*** 1536,1541 ****
--- 1537,1543 ----
    /* Detect circularities and truncate them.  */
    if (STRINGP (obj) || CONSP (obj) || VECTORP (obj)
        || COMPILEDP (obj) || CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj)
+       || HASH_TABLE_P (obj)
        || (! NILP (Vprint_gensym)
  	  && SYMBOLP (obj)
  	  && !SYMBOL_INTERNED_P (obj)))
***************
*** 2036,2041 ****
--- 2038,2044 ----
        else if (HASH_TABLE_P (obj))
  	{
  	  struct Lisp_Hash_Table *h = XHASH_TABLE (obj);
+ #if 0
  	  strout ("#<hash-table", -1, -1, printcharfun, 0);
  	  if (SYMBOLP (h->test))
  	    {
***************
*** 2052,2057 ****
--- 2055,2115 ----
  	  sprintf (buf, " 0x%lx", (unsigned long) h);
  	  strout (buf, -1, -1, printcharfun, 0);
  	  PRINTCHAR ('>');
+ #endif
+ 	  /*
+ 	    implement a readable output, e.g.:
+ 	    #s(hash-table size 2 test equal data (k1 v1 k2 v2))
+ 	  */
+ 	  /* always print the size */
+ 	  sprintf (buf, "#s(hash-table size %ld", (long) XVECTOR (h->next)->size);
+ 	  strout (buf, -1, -1, printcharfun, 0);
+ 
+ 	  if (!NILP(h->test))
+ 	    {
+ 	      strout (" test ", -1, -1, printcharfun, 0);
+ 	      print_object (h->test, printcharfun, 0);
+ 	    }
+ 
+ 	  if (!NILP(h->weak))
+ 	    {
+ 	      strout (" weakness ", -1, -1, printcharfun, 0);
+ 	      print_object (h->weak, printcharfun, 0);
+ 	    }
+ 
+ 	  if (!NILP(h->rehash_size))
+ 	    {
+ 	      strout (" rehash-size ", -1, -1, printcharfun, 0);
+ 	      print_object (h->rehash_size, printcharfun, 0);
+ 	    }
+ 
+ 	  if (!NILP(h->rehash_threshold))
+ 	    {
+ 	      strout (" rehash-threshold ", -1, -1, printcharfun, 0);
+ 	      print_object (h->rehash_threshold, printcharfun, 0);
+ 	    }
+ 
+ 	  strout (" data ", -1, -1, printcharfun, 0);
+ 
+ 	  /* print the data here as a plist */
+ 	  int i;
+ 	  int printed=0;
+ 
+ 	  PRINTCHAR ('(');
+ 	  for (i = 0; i < HASH_TABLE_SIZE (h); ++i)
+ 	    if (!NILP (HASH_HASH (h, i)))
+ 	      {
+ 		if (printed)
+ 		  {
+ 		    PRINTCHAR (' ');
+ 		  }
+ 		print_object (HASH_KEY (h, i), printcharfun, 0);
+ 		PRINTCHAR (' ');
+ 		print_object (HASH_VALUE (h, i), printcharfun, 0);
+ 		printed = 1;
+ 	      }
+ 	  PRINTCHAR (')');
+ 	  PRINTCHAR (')');
+ 
  	}
        else if (BUFFERP (obj))
  	{





^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-11-26 20:37                                                   ` Ted Zlatanov
  2008-11-26 21:16                                                     ` Ted Zlatanov
@ 2008-11-27  0:24                                                     ` Stephen J. Turnbull
  2008-12-01 21:53                                                       ` Ted Zlatanov
  1 sibling, 1 reply; 86+ messages in thread
From: Stephen J. Turnbull @ 2008-11-27  0:24 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

Ted Zlatanov writes:
 > On Wed, 26 Nov 2008 13:10:38 -0500 Stefan Monnier <monnier@iro.umontreal.ca> wrote: 

 > >> IMHO hashtables should always be printed completely and should be
 > >> treated like lists and vectors.

XEmacs abbreviates all "large" atomic objects in Lisp backtraces,
AFAIK.  This includes anything with a plist.  But you can have your
preference by setting `print-readably' globally.

 > >> If, however, compatibility with XEmacs is desired or people feel
 > >> strongly for print-readably, I will implement with
 > >> print-readably.
 > 
 > SM> char tables are always printed in full and we haven't had any complaints
 > SM> about that, so you're probably right: let's just always print them
 > SM> in full.  If it turns out to be problematic in some cases, we can later
 > SM> on add some extra variable to control the level of detail.
 > 
 > Great.  Maybe XEmacs should add print-unreadably ;)

We already have that. (^^;





^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-11-27  0:24                                                     ` Stephen J. Turnbull
@ 2008-12-01 21:53                                                       ` Ted Zlatanov
  2008-12-02  9:05                                                         ` Stephen J. Turnbull
  2008-12-02 22:19                                                         ` Stefan Monnier
  0 siblings, 2 replies; 86+ messages in thread
From: Ted Zlatanov @ 2008-12-01 21:53 UTC (permalink / raw)
  To: emacs-devel

On Thu, 27 Nov 2008 09:24:34 +0900 "Stephen J. Turnbull" <stephen@xemacs.org> wrote: 

SJT> Ted Zlatanov writes:
>> On Wed, 26 Nov 2008 13:10:38 -0500 Stefan Monnier <monnier@iro.umontreal.ca> wrote: 

>> >> IMHO hashtables should always be printed completely and should be
>> >> treated like lists and vectors.

SJT> XEmacs abbreviates all "large" atomic objects in Lisp backtraces,
SJT> AFAIK.  This includes anything with a plist.  But you can have your
SJT> preference by setting `print-readably' globally.

>> >> If, however, compatibility with XEmacs is desired or people feel
>> >> strongly for print-readably, I will implement with
>> >> print-readably.
>> 
SM> char tables are always printed in full and we haven't had any complaints
SM> about that, so you're probably right: let's just always print them
SM> in full.  If it turns out to be problematic in some cases, we can later
SM> on add some extra variable to control the level of detail.
>> 
>> Great.  Maybe XEmacs should add print-unreadably ;)

SJT> We already have that. (^^;

Can you and Stefan figure out whether to have print-readably or not?  I
was against it, and Stefan supported that.  But let's see the pro
argument and discuss this.  I'd like to make your life easier in
addition to providing features for GNU Emacs.  Will the current state of
things cause XEmacs breakage anywhere?

One idea I had is to check if print-readably is bound; if not then we
act as if it was bound and t.  That will DTRT in GNU Emacs and in
XEmacs, I hope.

Thanks
Ted





^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-11-26 21:16                                                     ` Ted Zlatanov
@ 2008-12-01 22:01                                                       ` Ted Zlatanov
  2008-12-02  0:13                                                         ` Andreas Schwab
                                                                           ` (2 more replies)
  0 siblings, 3 replies; 86+ messages in thread
From: Ted Zlatanov @ 2008-12-01 22:01 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1987 bytes --]

On Wed, 26 Nov 2008 15:16:41 -0600 Ted Zlatanov <tzz@lifelogs.com> wrote: 

TZ> The patch below does all the previously discussed formatting plus
TZ> detection of circular references and Davis Herring's suggestion of
TZ> skipping the first preliminary space.  The old-style hashtable printout
TZ> is disabled with an #ifdef, so only the new style is available.

The attached patch does reading and writing of hashtables.  I believe
it works correctly and handles the common error cases.  Please review.

Here are the issues:

- I don't know how to manage a dynamic array of Lisp_Object objects, as
  make-hash-table wants.  What I have right now is hacky and breaks for
  more than 5 parameters (e.g. reading #s(hash-table size 4 size 5 size
  4 size 5 size 4 weakness x) will ignore the weakness parameter.
  Ideally I'd put the arguments in a list and pass that off to
  make-hash-table, but I couldn't find an example of that in the source
  (casting a list of an array of Lisp_Object elements).  Additionally I
  use xmalloc without freeing the memory; I don't know if that will
  cause issues but I saw it used in other places without freeing the
  memory.

- it seems to me that
		      EQ(head, Qhash_table_size_marker) ||
		      EQ(head, Qhash_table_test_marker) ||
		      EQ(head, Qhash_table_weakness_marker) ||
		      EQ(head, Qhash_table_rehash_size_marker) ||
		      EQ(head, Qhash_table_rehash_threshold_marker))
  can be written better, but I don't know enough to do it right.  In
  addition, I don't know how to convert all those parameters to their :
  plist version, e.g. size => :size.  I'm sure it's trivial but couldn't
  find it in the source.  I really wish I could write all this in ELisp :)

- my code is very deliberate, using CAR_SAFE and CDR_SAFE a lot.  If
  that causes performance issues, please suggest improvements.  Ditto
  for anything else--remember this is my first trip to the C side of
  Emacs and treat everything with suspicion.

Thanks
Ted


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: hashprint.patch --]
[-- Type: text/x-diff, Size: 6766 bytes --]

? hashprint.patch
Index: lread.c
===================================================================
RCS file: /sources/emacs/emacs/src/lread.c,v
retrieving revision 1.401
diff -u -r1.401 lread.c
--- lread.c	7 Sep 2008 20:41:10 -0000	1.401
+++ lread.c	1 Dec 2008 21:48:58 -0000
@@ -80,6 +80,13 @@
 extern int errno;
 #endif
 
+/* hash table read constants */
+Lisp_Object Qhash_table_read_marker, Qhash_table_data_marker;
+Lisp_Object Qhash_table_test_marker, Qhash_table_size_marker;
+Lisp_Object Qhash_table_weakness_marker;
+Lisp_Object Qhash_table_rehash_size_marker;
+Lisp_Object Qhash_table_rehash_threshold_marker;
+
 Lisp_Object Qread_char, Qget_file_char, Qstandard_input, Qcurrent_load_list;
 Lisp_Object Qvariable_documentation, Vvalues, Vstandard_input, Vafter_load_alist;
 Lisp_Object Qascii_character, Qload, Qload_file_name;
@@ -2341,6 +2348,89 @@
 
     case '#':
       c = READCHAR;
+      if (c == 's')
+	{
+	  c = READCHAR;
+	  if (c == '(')
+	    {
+	      /*
+		Accept extended format for hashtables (extensible to
+		other types), e.g.
+		#s(hash-table size 2 test equal data (k1 v1 k2 v2))	     
+	      */
+	      Lisp_Object tmp = read_list (0, readcharfun);
+	      Lisp_Object head = CAR_SAFE(tmp);
+	      Lisp_Object data = Qnil;
+	      Lisp_Object val = Qnil;
+	      /* will this be freed automatically? */	      
+	      Lisp_Object* params = (Lisp_Object*) xmalloc (10 * sizeof(Lisp_Object));
+	      int param_count = 0;
+	      if (!EQ (head, Qhash_table_read_marker))
+		error ("Invalid extended read marker at head of #s list"
+		       "(only hash-table allowed)");
+
+	      while (!NILP(tmp))
+		{
+		  tmp = CDR_SAFE(tmp);
+		  head = CAR_SAFE(tmp);
+		  /* allowed parameters: size test weakness
+		     rehash-size rehash-threshold */
+		  if (EQ(head, Qhash_table_data_marker))
+		    {
+		      tmp = CDR_SAFE(tmp);
+		      data = CAR_SAFE(tmp);
+		      /* debug_print(data); */
+		    }
+
+		  if (
+		      param_count < 9 &&
+		      EQ(head, Qhash_table_size_marker) ||
+		      EQ(head, Qhash_table_test_marker) ||
+		      EQ(head, Qhash_table_weakness_marker) ||
+		      EQ(head, Qhash_table_rehash_size_marker) ||
+		      EQ(head, Qhash_table_rehash_threshold_marker))
+		    {
+		      tmp = CDR_SAFE(tmp);
+		      val = CAR_SAFE(tmp);
+		      /*
+			debug_print(head);
+			debug_print(val);
+		      */
+		      /* how do I turn head into a symbol with the same contents but beginning with ':'? */
+		      params[param_count] = head;
+		      params[param_count+1] = val;
+		      param_count+=2;
+		    }
+		}
+
+	      if (NILP(data))
+		error ("No data marker was found in the hash table");
+
+	      /* doesn't work because of 'size' vs. ':size' issue, see above
+		 Lisp_Object ht = Fmake_hash_table(param_count, params);
+	      */
+	      Lisp_Object ht = Fmake_hash_table(0, NULL);
+
+	      Lisp_Object key = Qnil;
+	      
+	      while (!NILP(data))
+		{
+		  key = CAR_SAFE(data);
+		  data = CDR_SAFE(data);
+		  val = CAR_SAFE(data);
+		  data = CDR_SAFE(data);
+		  if (NILP(val))
+		    error ("Odd number of elements in hashtable data");
+		  /*
+		    debug_print(key);
+		    debug_print(val);
+		  */
+		  Fputhash(key, val, ht);
+		}
+	      
+	      return ht;
+	    }	
+	}
       if (c == '^')
 	{
 	  c = READCHAR;
@@ -4432,6 +4522,21 @@
 
   Vloads_in_progress = Qnil;
   staticpro (&Vloads_in_progress);
+
+  Qhash_table_read_marker = intern ("hash-table");
+  staticpro (&Qhash_table_read_marker);
+  Qhash_table_data_marker = intern ("data");
+  staticpro (&Qhash_table_data_marker);
+  Qhash_table_test_marker = intern ("test");
+  staticpro (&Qhash_table_size_marker);
+  Qhash_table_test_marker = intern ("size");
+  staticpro (&Qhash_table_size_marker);
+  Qhash_table_weakness_marker = intern ("weakness");
+  staticpro (&Qhash_table_weakness_marker);
+  Qhash_table_rehash_size_marker = intern ("rehash-size");
+  staticpro (&Qhash_table_rehash_size_marker);
+  Qhash_table_rehash_threshold_marker = intern ("rehash-threshold");
+  staticpro (&Qhash_table_rehash_threshold_marker);
 }
 
 /* arch-tag: a0d02733-0f96-4844-a659-9fd53c4f414d
Index: print.c
===================================================================
RCS file: /sources/emacs/emacs/src/print.c,v
retrieving revision 1.253
diff -u -r1.253 print.c
--- print.c	31 Jul 2008 05:33:53 -0000	1.253
+++ print.c	1 Dec 2008 21:48:58 -0000
@@ -1341,6 +1341,7 @@
  loop:
   if (STRINGP (obj) || CONSP (obj) || VECTORP (obj)
       || COMPILEDP (obj) || CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj)
+      || HASH_TABLE_P (obj)
       || (! NILP (Vprint_gensym)
 	  && SYMBOLP (obj)
 	  && !SYMBOL_INTERNED_P (obj)))
@@ -1536,6 +1537,7 @@
   /* Detect circularities and truncate them.  */
   if (STRINGP (obj) || CONSP (obj) || VECTORP (obj)
       || COMPILEDP (obj) || CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj)
+      || HASH_TABLE_P (obj)
       || (! NILP (Vprint_gensym)
 	  && SYMBOLP (obj)
 	  && !SYMBOL_INTERNED_P (obj)))
@@ -2036,6 +2038,7 @@
       else if (HASH_TABLE_P (obj))
 	{
 	  struct Lisp_Hash_Table *h = XHASH_TABLE (obj);
+#if 0
 	  strout ("#<hash-table", -1, -1, printcharfun, 0);
 	  if (SYMBOLP (h->test))
 	    {
@@ -2052,6 +2055,61 @@
 	  sprintf (buf, " 0x%lx", (unsigned long) h);
 	  strout (buf, -1, -1, printcharfun, 0);
 	  PRINTCHAR ('>');
+#endif
+	  /*
+	    implement a readable output, e.g.:
+	    #s(hash-table size 2 test equal data (k1 v1 k2 v2))
+	  */
+	  /* always print the size */
+	  sprintf (buf, "#s(hash-table size %ld", (long) XVECTOR (h->next)->size);
+	  strout (buf, -1, -1, printcharfun, 0);
+
+	  if (!NILP(h->test))
+	    {
+	      strout (" test ", -1, -1, printcharfun, 0);
+	      print_object (h->test, printcharfun, 0);
+	    }
+
+	  if (!NILP(h->weak))
+	    {
+	      strout (" weakness ", -1, -1, printcharfun, 0);
+	      print_object (h->weak, printcharfun, 0);
+	    }
+
+	  if (!NILP(h->rehash_size))
+	    {
+	      strout (" rehash-size ", -1, -1, printcharfun, 0);
+	      print_object (h->rehash_size, printcharfun, 0);
+	    }
+
+	  if (!NILP(h->rehash_threshold))
+	    {
+	      strout (" rehash-threshold ", -1, -1, printcharfun, 0);
+	      print_object (h->rehash_threshold, printcharfun, 0);
+	    }
+
+	  strout (" data ", -1, -1, printcharfun, 0);
+
+	  /* print the data here as a plist */
+	  int i;
+	  int printed=0;
+
+	  PRINTCHAR ('(');
+	  for (i = 0; i < HASH_TABLE_SIZE (h); ++i)
+	    if (!NILP (HASH_HASH (h, i)))
+	      {
+		if (printed)
+		  {
+		    PRINTCHAR (' ');
+		  }
+		print_object (HASH_KEY (h, i), printcharfun, 0);
+		PRINTCHAR (' ');
+		print_object (HASH_VALUE (h, i), printcharfun, 0);
+		printed = 1;
+	      }
+	  PRINTCHAR (')');
+	  PRINTCHAR (')');
+
 	}
       else if (BUFFERP (obj))
 	{

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-12-01 22:01                                                       ` Ted Zlatanov
@ 2008-12-02  0:13                                                         ` Andreas Schwab
  2008-12-02 14:27                                                           ` Ted Zlatanov
  2008-12-02 21:59                                                           ` Stefan Monnier
  2008-12-02 20:56                                                         ` Ted Zlatanov
  2008-12-02 21:58                                                         ` Stefan Monnier
  2 siblings, 2 replies; 86+ messages in thread
From: Andreas Schwab @ 2008-12-02  0:13 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

Ted Zlatanov <tzz@lifelogs.com> writes:

>   I really wish I could write all this in ELisp :)

That should be fairly easy by introducing a variable, say,
hash-table-reader-function and just calling its value when set (and
bailing out if not).  That can then be implemented fully in Lisp.

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
PGP key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-12-01 21:53                                                       ` Ted Zlatanov
@ 2008-12-02  9:05                                                         ` Stephen J. Turnbull
  2008-12-02 14:21                                                           ` Ted Zlatanov
  2008-12-02 22:19                                                         ` Stefan Monnier
  1 sibling, 1 reply; 86+ messages in thread
From: Stephen J. Turnbull @ 2008-12-02  9:05 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

Ted Zlatanov writes:

 > Can you and Stefan figure out whether to have print-readably or
 > not?  I was against it, and Stefan supported that.  But let's see
 > the pro argument and discuss this.

The pro argument is that unless you're debugging the hash table, it's
a PITA to have a hash table that gets recursively passed to each
function down the line taking up 20 screens for each frame in a
backtrace.  "Not debugging the hash table" is the overwhelmingly
common occurance for me; usually I'm more interested in where in the
stack the value I'm going to be puthash'ing turned from gold into
garbage.  OTOH, about half the time when I've got a chartable in the
stack, the chartable is buggy (in my experience almost all chartables
are write-once).

 > Will the current state of things cause XEmacs breakage anywhere?

No.  This is a user interface thing.  If I'm right, XEmacs will get a
mild popularity boost if you always print the hash table.  I'm not
going to complain about that! ;-)

 > One idea I had is to check if print-readably is bound; if not then
 > we act as if it was bound and t.  That will DTRT in GNU Emacs and
 > in XEmacs, I hope.

Hm?  XEmacs already has the feature in C; your code will either get
ignored in XEmacs syncs, or its algorithms will be ported to our C
code.  Definitely not something for you to worry about.






^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-12-02  9:05                                                         ` Stephen J. Turnbull
@ 2008-12-02 14:21                                                           ` Ted Zlatanov
  2008-12-02 15:54                                                             ` Stephen J. Turnbull
  0 siblings, 1 reply; 86+ messages in thread
From: Ted Zlatanov @ 2008-12-02 14:21 UTC (permalink / raw)
  To: emacs-devel

On Tue, 02 Dec 2008 18:05:52 +0900 "Stephen J. Turnbull" <stephen@xemacs.org> wrote: 

SJT> Ted Zlatanov writes:
>> Can you and Stefan figure out whether to have print-readably or
>> not?  I was against it, and Stefan supported that.  But let's see
>> the pro argument and discuss this.

SJT> The pro argument is that unless you're debugging the hash table, it's
SJT> a PITA to have a hash table that gets recursively passed to each
SJT> function down the line taking up 20 screens for each frame in a
SJT> backtrace.  "Not debugging the hash table" is the overwhelmingly
SJT> common occurance for me; usually I'm more interested in where in the
SJT> stack the value I'm going to be puthash'ing turned from gold into
SJT> garbage.  OTOH, about half the time when I've got a chartable in the
SJT> stack, the chartable is buggy (in my experience almost all chartables
SJT> are write-once).

Isn't the same argument valid for lists?  At least in the Emacs
backtrace, lists get shortened for display; I don't know if that's done
at the print level or at the display level.  If it's at the display
level, a lot of cycles are wasted for large lists.

Basically I want to treat hashtables like lists as much as possible for
printing and reading, so print-readably would introduce inconsistency.
Otherwise I agree with your argument, I am just reluctant to make
hashtables an exception to the general print behavior.

>> Will the current state of things cause XEmacs breakage anywhere?

SJT> No.  This is a user interface thing.  If I'm right, XEmacs will get a
SJT> mild popularity boost if you always print the hash table.  I'm not
SJT> going to complain about that! ;-)

Heh.

>> One idea I had is to check if print-readably is bound; if not then
>> we act as if it was bound and t.  That will DTRT in GNU Emacs and
>> in XEmacs, I hope.

SJT> Hm?  XEmacs already has the feature in C; your code will either get
SJT> ignored in XEmacs syncs, or its algorithms will be ported to our C
SJT> code.  Definitely not something for you to worry about.

Great.

Ted





^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-12-02  0:13                                                         ` Andreas Schwab
@ 2008-12-02 14:27                                                           ` Ted Zlatanov
  2008-12-02 21:59                                                           ` Stefan Monnier
  1 sibling, 0 replies; 86+ messages in thread
From: Ted Zlatanov @ 2008-12-02 14:27 UTC (permalink / raw)
  To: emacs-devel

On Tue, 02 Dec 2008 01:13:49 +0100 Andreas Schwab <schwab@suse.de> wrote: 

AS> Ted Zlatanov <tzz@lifelogs.com> writes:
>> I really wish I could write all this in ELisp :)

AS> That should be fairly easy by introducing a variable, say,
AS> hash-table-reader-function and just calling its value when set (and
AS> bailing out if not).  That can then be implemented fully in Lisp.

Yes, I considered that, but I'm potentially reading thousands of entries
so I wanted to keep the code as fast as possible.  

Splitting the code into an ELisp setup phase and a C fast data filler is
probably the easiest solution if I go that route, but I have to say I
enjoyed my trip in the C side of Emacs so I'd like to figure out the C
way to do what I proposed.  Specifically, converting a C LispObject
holding the symbol "test" to the symbol ":test" without hard-coding, and
passing an array of LispObject elements to make-hash-table, are my main
issues right now.

Ted





^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-12-02 14:21                                                           ` Ted Zlatanov
@ 2008-12-02 15:54                                                             ` Stephen J. Turnbull
  2008-12-02 16:10                                                               ` Ted Zlatanov
  0 siblings, 1 reply; 86+ messages in thread
From: Stephen J. Turnbull @ 2008-12-02 15:54 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

Ted Zlatanov writes:
 > On Tue, 02 Dec 2008 18:05:52 +0900 "Stephen J. Turnbull" <stephen@xemacs.org> wrote: 
 > 
 > SJT> Ted Zlatanov writes:
 > >> Can you and Stefan figure out whether to have print-readably or
 > >> not?  I was against it, and Stefan supported that.  But let's see
 > >> the pro argument and discuss this.
 > 
 > SJT> The pro argument is that unless you're debugging the hash table, it's
 > SJT> a PITA to have a hash table that gets recursively passed to each
 > SJT> function down the line taking up 20 screens for each frame in a
 > SJT> backtrace.
 > 
 > Isn't the same argument valid for lists?

No.  You don't know whether a list is data or an executable expression
in Lisp until you eval it.  Lists are special.  A comparison to
vectors might be more appropriate.





^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-12-02 15:54                                                             ` Stephen J. Turnbull
@ 2008-12-02 16:10                                                               ` Ted Zlatanov
  2008-12-02 16:54                                                                 ` Stephen J. Turnbull
  0 siblings, 1 reply; 86+ messages in thread
From: Ted Zlatanov @ 2008-12-02 16:10 UTC (permalink / raw)
  To: emacs-devel

On Wed, 03 Dec 2008 00:54:49 +0900 "Stephen J. Turnbull" <stephen@xemacs.org> wrote: 

SJT> Ted Zlatanov writes:
>> On Tue, 02 Dec 2008 18:05:52 +0900 "Stephen J. Turnbull" <stephen@xemacs.org> wrote: 
>> 
SJT> Ted Zlatanov writes:
>> >> Can you and Stefan figure out whether to have print-readably or
>> >> not?  I was against it, and Stefan supported that.  But let's see
>> >> the pro argument and discuss this.
>> 
SJT> The pro argument is that unless you're debugging the hash table, it's
SJT> a PITA to have a hash table that gets recursively passed to each
SJT> function down the line taking up 20 screens for each frame in a
SJT> backtrace.
>> 
>> Isn't the same argument valid for lists?

SJT> No.  You don't know whether a list is data or an executable expression
SJT> in Lisp until you eval it.  Lists are special.  A comparison to
SJT> vectors might be more appropriate.

OK, that makes sense.  I checked the source and I think the relevant GNU
Emacs variables are eval-expression-print-length and print-length, which
it affects.  They control how many vector/bitvector elements are
printed.  Would it work to say:

;; pseudo-lisp
(when (and (bound-and-not-nil print-readably) 
           (not (natnump print-length)))
 (setq print-length 10))

Ted





^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-12-02 16:10                                                               ` Ted Zlatanov
@ 2008-12-02 16:54                                                                 ` Stephen J. Turnbull
  0 siblings, 0 replies; 86+ messages in thread
From: Stephen J. Turnbull @ 2008-12-02 16:54 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

Ted Zlatanov writes:

 > OK, that makes sense.  I checked the source and I think the relevant GNU
 > Emacs variables are eval-expression-print-length and print-length, which
 > it affects.  They control how many vector/bitvector elements are
 > printed.  Would it work to say:

Well, that's not really for me to say.  I can advise you on the basis
of XEmacs experience and the rationales I've heard from the people who
wrote the code, but whether that makes sense/is to the taste of Emacs
users is something that ultimately Stefan and Yidong have to judge.

If you haven't heard something *convincing* to you by now, I think you
should take the easy way out, and just print everything until somebody
complains.  That's what you personally need anyway, right?

IOW, I think at this point we're discussing the color of the trim on
the bikeshed.... :-)




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-12-01 22:01                                                       ` Ted Zlatanov
  2008-12-02  0:13                                                         ` Andreas Schwab
@ 2008-12-02 20:56                                                         ` Ted Zlatanov
  2008-12-02 21:27                                                           ` Andreas Schwab
  2008-12-02 21:58                                                         ` Stefan Monnier
  2 siblings, 1 reply; 86+ messages in thread
From: Ted Zlatanov @ 2008-12-02 20:56 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1199 bytes --]

The attached patch does print and read of hashtables.  It respects
print-length only, exactly like vector print and consistent with the
rest of GNU Emacs.  Please review and comment.  Some notes:

I ended up with this code to put a list into Fmake_hash_table format
('params' is a Lisp_Object that holds a bunch of conses).

	      int param_count = 0;
	      Lisp_Object *pa = (Lisp_Object*) xmalloc(XFASTINT(Flength(params)) * sizeof(Lisp_Object));

	      while (!NILP(params))
		{
		  pa[param_count++] = CAR_SAFE(params);
		  params = CDR_SAFE(params);
		}

	      Lisp_Object ht = Fmake_hash_table(param_count, pa);

I would prefer it if I could avoid all that work, but it seems (from
reading lisp.h and hunting for similar code) that it must be done as
above.  I don't see a macro to convert a Lisp_Object that holds a list
into the Lisp_Object* that a lot of functions need.

Also I don't know if what xmalloc() gives needs to be freed eventually.

To generate the Lisp symbol ":size" from the symbol "size" for example,
I used:

Lisp_Object colon = make_string (":", 1);
intern(SDATA(concat2(colon, SYMBOL_NAME(head))))

I don't know if there's a better way, but this works.

Thanks!
Ted


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: hashprint.patch --]
[-- Type: text/x-diff, Size: 6975 bytes --]

? hashprint.patch
Index: lread.c
===================================================================
RCS file: /sources/emacs/emacs/src/lread.c,v
retrieving revision 1.401
diff -u -r1.401 lread.c
--- lread.c	7 Sep 2008 20:41:10 -0000	1.401
+++ lread.c	2 Dec 2008 20:46:34 -0000
@@ -80,6 +80,13 @@
 extern int errno;
 #endif
 
+/* hash table read constants */
+Lisp_Object Qhash_table_read_marker, Qhash_table_data_marker;
+Lisp_Object Qhash_table_test_marker, Qhash_table_size_marker;
+Lisp_Object Qhash_table_weakness_marker;
+Lisp_Object Qhash_table_rehash_size_marker;
+Lisp_Object Qhash_table_rehash_threshold_marker;
+
 Lisp_Object Qread_char, Qget_file_char, Qstandard_input, Qcurrent_load_list;
 Lisp_Object Qvariable_documentation, Vvalues, Vstandard_input, Vafter_load_alist;
 Lisp_Object Qascii_character, Qload, Qload_file_name;
@@ -2341,6 +2348,94 @@
 
     case '#':
       c = READCHAR;
+      if (c == 's')
+	{
+	  c = READCHAR;
+	  if (c == '(')
+	    {
+	      /*
+		Accept extended format for hashtables (extensible to
+		other types), e.g.
+		#s(hash-table size 2 test equal data (k1 v1 k2 v2))	     
+	      */
+	      Lisp_Object tmp = read_list (0, readcharfun);
+	      Lisp_Object head = CAR_SAFE(tmp);
+	      Lisp_Object data = Qnil;
+	      Lisp_Object val = Qnil;
+	      Lisp_Object params = Qnil;
+	      Lisp_Object colon = make_string (":", 1);
+	      
+	      if (!EQ (head, Qhash_table_read_marker))
+		error ("Invalid extended read marker at head of #s list"
+		       "(only hash-table allowed)");
+
+	      while (!NILP(tmp))
+		{
+		  tmp = CDR_SAFE(tmp);
+		  head = CAR_SAFE(tmp);
+		  /* allowed parameters: size test weakness
+		     rehash-size rehash-threshold */
+		  if (EQ(head, Qhash_table_data_marker))
+		    {
+		      tmp = CDR_SAFE(tmp);
+		      data = CAR_SAFE(tmp);
+		    }
+
+		  if (
+		      EQ(head, Qhash_table_size_marker) ||
+		      EQ(head, Qhash_table_test_marker) ||
+		      EQ(head, Qhash_table_weakness_marker) ||
+		      EQ(head, Qhash_table_rehash_size_marker) ||
+		      EQ(head, Qhash_table_rehash_threshold_marker))
+		    {
+		      tmp = CDR_SAFE(tmp);
+		      val = CAR_SAFE(tmp);
+		      params = Fcons(val, params);
+		      params = Fcons(intern(SDATA(concat2(colon,
+							  SYMBOL_NAME(head)))),
+				     params);
+		      debug_print(params);
+		      /*
+			debug_print(head);
+			debug_print(val);
+		      */
+		    }
+		}
+
+	      if (NILP(data))
+		error ("No data marker was found in the hash table");
+
+	      int param_count = 0;
+	      Lisp_Object *pa = (Lisp_Object*) xmalloc(XFASTINT(Flength(params)) * sizeof(Lisp_Object));
+
+	      while (!NILP(params))
+		{
+		  pa[param_count++] = CAR_SAFE(params);
+		  params = CDR_SAFE(params);
+		}
+
+	      Lisp_Object ht = Fmake_hash_table(param_count, pa);
+
+	      Lisp_Object key = Qnil;
+	      
+	      while (!NILP(data))
+		{
+		  key = CAR_SAFE(data);
+		  data = CDR_SAFE(data);
+		  val = CAR_SAFE(data);
+		  data = CDR_SAFE(data);
+		  if (NILP(val))
+		    error ("Odd number of elements in hashtable data");
+		  /*
+		    debug_print(key);
+		    debug_print(val);
+		  */
+		  Fputhash(key, val, ht);
+		}
+	      
+	      return ht;
+	    }	
+	}
       if (c == '^')
 	{
 	  c = READCHAR;
@@ -4432,6 +4527,21 @@
 
   Vloads_in_progress = Qnil;
   staticpro (&Vloads_in_progress);
+
+  Qhash_table_read_marker = intern ("hash-table");
+  staticpro (&Qhash_table_read_marker);
+  Qhash_table_data_marker = intern ("data");
+  staticpro (&Qhash_table_data_marker);
+  Qhash_table_test_marker = intern ("test");
+  staticpro (&Qhash_table_size_marker);
+  Qhash_table_test_marker = intern ("size");
+  staticpro (&Qhash_table_size_marker);
+  Qhash_table_weakness_marker = intern ("weakness");
+  staticpro (&Qhash_table_weakness_marker);
+  Qhash_table_rehash_size_marker = intern ("rehash-size");
+  staticpro (&Qhash_table_rehash_size_marker);
+  Qhash_table_rehash_threshold_marker = intern ("rehash-threshold");
+  staticpro (&Qhash_table_rehash_threshold_marker);
 }
 
 /* arch-tag: a0d02733-0f96-4844-a659-9fd53c4f414d
Index: print.c
===================================================================
RCS file: /sources/emacs/emacs/src/print.c,v
retrieving revision 1.253
diff -u -r1.253 print.c
--- print.c	31 Jul 2008 05:33:53 -0000	1.253
+++ print.c	2 Dec 2008 20:46:34 -0000
@@ -1341,6 +1341,7 @@
  loop:
   if (STRINGP (obj) || CONSP (obj) || VECTORP (obj)
       || COMPILEDP (obj) || CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj)
+      || HASH_TABLE_P (obj)
       || (! NILP (Vprint_gensym)
 	  && SYMBOLP (obj)
 	  && !SYMBOL_INTERNED_P (obj)))
@@ -1536,6 +1537,7 @@
   /* Detect circularities and truncate them.  */
   if (STRINGP (obj) || CONSP (obj) || VECTORP (obj)
       || COMPILEDP (obj) || CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj)
+      || HASH_TABLE_P (obj)
       || (! NILP (Vprint_gensym)
 	  && SYMBOLP (obj)
 	  && !SYMBOL_INTERNED_P (obj)))
@@ -2036,6 +2038,7 @@
       else if (HASH_TABLE_P (obj))
 	{
 	  struct Lisp_Hash_Table *h = XHASH_TABLE (obj);
+#if 0
 	  strout ("#<hash-table", -1, -1, printcharfun, 0);
 	  if (SYMBOLP (h->test))
 	    {
@@ -2052,6 +2055,68 @@
 	  sprintf (buf, " 0x%lx", (unsigned long) h);
 	  strout (buf, -1, -1, printcharfun, 0);
 	  PRINTCHAR ('>');
+#endif
+	  /*
+	    implement a readable output, e.g.:
+	    #s(hash-table size 2 test equal data (k1 v1 k2 v2))
+	  */
+	  /* always print the size */
+	  sprintf (buf, "#s(hash-table size %ld", (long) XVECTOR (h->next)->size);
+	  strout (buf, -1, -1, printcharfun, 0);
+
+	  if (!NILP(h->test))
+	    {
+	      strout (" test ", -1, -1, printcharfun, 0);
+	      print_object (h->test, printcharfun, 0);
+	    }
+
+	  if (!NILP(h->weak))
+	    {
+	      strout (" weakness ", -1, -1, printcharfun, 0);
+	      print_object (h->weak, printcharfun, 0);
+	    }
+
+	  if (!NILP(h->rehash_size))
+	    {
+	      strout (" rehash-size ", -1, -1, printcharfun, 0);
+	      print_object (h->rehash_size, printcharfun, 0);
+	    }
+
+	  if (!NILP(h->rehash_threshold))
+	    {
+	      strout (" rehash-threshold ", -1, -1, printcharfun, 0);
+	      print_object (h->rehash_threshold, printcharfun, 0);
+	    }
+
+	  strout (" data ", -1, -1, printcharfun, 0);
+
+	  /* print the data here as a plist */
+	  int i;
+
+	  int real_size = HASH_TABLE_SIZE (h);
+	  int size = real_size;
+
+	  /* Don't print more elements than the specified maximum.  */
+	  if (NATNUMP (Vprint_length)
+	      && XFASTINT (Vprint_length) < size)
+	    size = XFASTINT (Vprint_length);
+	  
+	  PRINTCHAR ('(');
+	  for (i = 0; i < size; i++)
+	    if (!NILP (HASH_HASH (h, i)))
+	      {
+		if (i) PRINTCHAR (' ');
+		print_object (HASH_KEY (h, i), printcharfun, 0);
+		PRINTCHAR (' ');
+		print_object (HASH_VALUE (h, i), printcharfun, 0);
+	      }
+
+	  if (size < real_size)
+	    strout (" ...", 4, 4, printcharfun, 0);
+
+	  PRINTCHAR (')');
+	  PRINTCHAR (')');
+
 	}
       else if (BUFFERP (obj))
 	{

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-12-02 20:56                                                         ` Ted Zlatanov
@ 2008-12-02 21:27                                                           ` Andreas Schwab
  0 siblings, 0 replies; 86+ messages in thread
From: Andreas Schwab @ 2008-12-02 21:27 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

Ted Zlatanov <tzz@lifelogs.com> writes:

> I ended up with this code to put a list into Fmake_hash_table format
> ('params' is a Lisp_Object that holds a bunch of conses).
>
> 	      int param_count = 0;
> 	      Lisp_Object *pa = (Lisp_Object*) xmalloc(XFASTINT(Flength(params)) * sizeof(Lisp_Object));
>
> 	      while (!NILP(params))
> 		{
> 		  pa[param_count++] = CAR_SAFE(params);
> 		  params = CDR_SAFE(params);
> 		}
>
> 	      Lisp_Object ht = Fmake_hash_table(param_count, pa);

This is of course a memory leak, since pa is never freed.

> I would prefer it if I could avoid all that work, but it seems (from
> reading lisp.h and hunting for similar code) that it must be done as
> above.  I don't see a macro to convert a Lisp_Object that holds a list
> into the Lisp_Object* that a lot of functions need.

Since you know the max size of the array, just declare it as such.

(One more reason to implement it in Lisp.)

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
PGP key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-12-01 22:01                                                       ` Ted Zlatanov
  2008-12-02  0:13                                                         ` Andreas Schwab
  2008-12-02 20:56                                                         ` Ted Zlatanov
@ 2008-12-02 21:58                                                         ` Stefan Monnier
  2008-12-03 19:25                                                           ` Ted Zlatanov
  2 siblings, 1 reply; 86+ messages in thread
From: Stefan Monnier @ 2008-12-02 21:58 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

> +	      /* will this be freed automatically? */
> +	      Lisp_Object* params = (Lisp_Object*) xmalloc (10 * sizeof(Lisp_Object));

No, it won't be freed automatically.  Why not use `alloca' instead?
Also rather than 10, why not use something like XINT (Flength (tmp)) ?

> +	      if (!EQ (head, Qhash_table_read_marker))

This constant should be called Qhash_table.

> +	      while (!NILP(tmp))
> +		{
> +		  tmp = CDR_SAFE(tmp);
> +		  head = CAR_SAFE(tmp);

If you replace !NILP with CONSP, you can replace CDR_SAFE with XCDR
(which is more efficient since it presumes you've done the CONSP test
earlier).

> +		  /* allowed parameters: size test weakness
> +		     rehash-size rehash-threshold */

Why not :weakness, :rehash-size, :rehash-threshold?
(maybe even :test and :size, although IIUC we may prefer just `size'
and `test' for compatibility with XEmacs, tho I'm not sure how
important that is for this kind of data).

> +		  if (EQ(head, Qhash_table_data_marker))

It should just be called Qdata.  Also you need to put spaces before all
your open parens.

> +		    {
> +		      tmp = CDR_SAFE(tmp);
> +		      data = CAR_SAFE(tmp);
> +		      /* debug_print(data); */
> +		    }
> +
> +		  if (
> +		      param_count < 9 &&
> +		      EQ(head, Qhash_table_size_marker) ||
> +		      EQ(head, Qhash_table_test_marker) ||
> +		      EQ(head, Qhash_table_weakness_marker) ||
> +		      EQ(head, Qhash_table_rehash_size_marker) ||
> +		      EQ(head, Qhash_table_rehash_threshold_marker))
> +		    {
> +		      tmp = CDR_SAFE(tmp);
> +		      val = CAR_SAFE(tmp);
> +		      /*
> +			debug_print(head);
> +			debug_print(val);
> +		      */
> +		      /* how do I turn head into a symbol with the same contents but beginning with ':'? */
> +		      params[param_count] = head;
> +		      params[param_count+1] = val;
> +		      param_count+=2;
> +		    }
> +		}

How 'bout:

   {
      Lisp_Object params[10];
      params[0] = QCsize;
      params[1] = Fplist_get (Qsize, tmp);
      params[2] = QCtest;
      params[3] = Fplist_get (Qtest, tmp);
      params[4] = QCweakness;
      params[5] = Fplist_get (Qweakness, tmp);
      params[6] = QCrehash_size;
      params[7] = Fplist_get (Qrehash_size, tmp);
      params[8] = QCrehash_threshold;
      params[9] = Fplist_get (Qrehash_threshold, tmp);
   }

and then use Fplist_get (Qdata, tmp) to get the data?

> +	      if (NILP(data))
> +		error ("No data marker was found in the hash table");

Why bother?

> +	      while (!NILP(data))
> +		{
> +		  key = CAR_SAFE(data);
> +		  data = CDR_SAFE(data);
> +		  val = CAR_SAFE(data);
> +		  data = CDR_SAFE(data);
> +		  if (NILP(val))
> +		    error ("Odd number of elements in hashtable data");

This test doesn't look right.  What if the value stored for `key' is
indeed nil?  You could write it like that instead:

      while (CONSP (data))
	{
	  key = XCAR (data);
	  data = XCDR (data);
	  if (!CONSP (data))
	    error ("Odd number of elements in hashtable data");
	  val = XCAR (data);
	  data = XCDR (data);


-- Stefan




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-12-02  0:13                                                         ` Andreas Schwab
  2008-12-02 14:27                                                           ` Ted Zlatanov
@ 2008-12-02 21:59                                                           ` Stefan Monnier
  2008-12-02 22:20                                                             ` Andreas Schwab
  1 sibling, 1 reply; 86+ messages in thread
From: Stefan Monnier @ 2008-12-02 21:59 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: Ted Zlatanov, emacs-devel

>> I really wish I could write all this in ELisp :)
> That should be fairly easy by introducing a variable, say,
> hash-table-reader-function and just calling its value when set (and
> bailing out if not).  That can then be implemented fully in Lisp.

Yes, that would seem like a good idea, although I'm not sure how ready
the C reader code is to let elisp evaluation take place in the middle
of it, so we may find some trouble, but it's worth trying.


        Stefan




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-12-01 21:53                                                       ` Ted Zlatanov
  2008-12-02  9:05                                                         ` Stephen J. Turnbull
@ 2008-12-02 22:19                                                         ` Stefan Monnier
  2008-12-02 23:27                                                           ` Ted Zlatanov
  1 sibling, 1 reply; 86+ messages in thread
From: Stefan Monnier @ 2008-12-02 22:19 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

> Can you and Stefan figure out whether to have print-readably or not?  I

As I said, let's go with a "always print it all" approach for now.
You may want to make it obey print-length and print-depth, tho.


        Stefan




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-12-02 21:59                                                           ` Stefan Monnier
@ 2008-12-02 22:20                                                             ` Andreas Schwab
  0 siblings, 0 replies; 86+ messages in thread
From: Andreas Schwab @ 2008-12-02 22:20 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Ted Zlatanov, emacs-devel

Stefan Monnier <monnier@IRO.UMontreal.CA> writes:

> Yes, that would seem like a good idea, although I'm not sure how ready
> the C reader code is to let elisp evaluation take place in the middle
> of it, so we may find some trouble, but it's worth trying.

You can already have arbitrary lisp functions for reading characters.

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
PGP key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-12-02 22:19                                                         ` Stefan Monnier
@ 2008-12-02 23:27                                                           ` Ted Zlatanov
  0 siblings, 0 replies; 86+ messages in thread
From: Ted Zlatanov @ 2008-12-02 23:27 UTC (permalink / raw)
  To: emacs-devel

On Tue, 02 Dec 2008 17:19:55 -0500 Stefan Monnier <monnier@IRO.UMontreal.CA> wrote: 

>> Can you and Stefan figure out whether to have print-readably or not?  I
SM> As I said, let's go with a "always print it all" approach for now.
SM> You may want to make it obey print-length and print-depth, tho.

OK, my latest patch does that.

Ted





^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-12-02 21:58                                                         ` Stefan Monnier
@ 2008-12-03 19:25                                                           ` Ted Zlatanov
  2008-12-04  2:05                                                             ` Stefan Monnier
  0 siblings, 1 reply; 86+ messages in thread
From: Ted Zlatanov @ 2008-12-03 19:25 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1417 bytes --]

On Tue, 02 Dec 2008 16:58:41 -0500 Stefan Monnier <monnier@IRO.UMontreal.CA> wrote: 

>> +	      /* will this be freed automatically? */
>> +	      Lisp_Object* params = (Lisp_Object*) xmalloc (10 * sizeof(Lisp_Object));

SM> No, it won't be freed automatically.  Why not use `alloca' instead?
SM> Also rather than 10, why not use something like XINT (Flength (tmp)) ?

A static array was a much simpler solution in the end.

>> +	      if (!EQ (head, Qhash_table_read_marker))

SM> This constant should be called Qhash_table.

OK, all the constants are named appropriately.

>> +		  /* allowed parameters: size test weakness
>> +		     rehash-size rehash-threshold */

SM> Why not :weakness, :rehash-size, :rehash-threshold?
SM> (maybe even :test and :size, although IIUC we may prefer just `size'
SM> and `test' for compatibility with XEmacs, tho I'm not sure how
SM> important that is for this kind of data).

To be consistent.  If this will be used by many users and libraries,
it's important to provide a printed representation that doesn't mix
symbol conventions and is easy to parse.  Similarly, I'd rather provide
something compatible with XEmacs if there's a choice.

SM> Also you need to put spaces before all your open parens.

Done, thanks.

I took your other suggestions, except I don't pass Qnil parameters to
make-hash-table to keep things clean.  I hope this version of the patch
is acceptable.

Ted


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: hashprint.patch --]
[-- Type: text/x-diff, Size: 6577 bytes --]

? hashprint.patch
Index: lread.c
===================================================================
RCS file: /sources/emacs/emacs/src/lread.c,v
retrieving revision 1.401
diff -u -r1.401 lread.c
--- lread.c	7 Sep 2008 20:41:10 -0000	1.401
+++ lread.c	3 Dec 2008 19:17:59 -0000
@@ -80,6 +80,14 @@
 extern int errno;
 #endif
 
+/* hash table read constants */
+Lisp_Object Qhash_table, Qdata;
+Lisp_Object Qtest, Qsize;
+Lisp_Object Qweakness;
+Lisp_Object Qrehash_size;
+Lisp_Object Qrehash_threshold;
+extern Lisp_Object QCtest, QCsize, QCrehash_size, QCrehash_threshold, QCweakness;
+
 Lisp_Object Qread_char, Qget_file_char, Qstandard_input, Qcurrent_load_list;
 Lisp_Object Qvariable_documentation, Vvalues, Vstandard_input, Vafter_load_alist;
 Lisp_Object Qascii_character, Qload, Qload_file_name;
@@ -2341,6 +2349,72 @@
 
     case '#':
       c = READCHAR;
+      if (c == 's')
+	{
+	  c = READCHAR;
+	  if (c == '(')
+	    {
+	      /*
+		Accept extended format for hashtables (extensible to
+		other types), e.g.
+		#s(hash-table size 2 test equal data (k1 v1 k2 v2))	     
+	      */
+	      Lisp_Object tmp = read_list (0, readcharfun);
+	      Lisp_Object head = CAR_SAFE (tmp);
+	      Lisp_Object data = Qnil;
+	      Lisp_Object val = Qnil;
+	      /* 2 * number of allowed keywords to make-hash-table */
+	      Lisp_Object params[10]; 
+	      int param_count = 0;
+	      int i;
+	      
+	      if (!EQ (head, Qhash_table))
+		error ("Invalid extended read marker at head of #s list "
+		       "(only hash-table allowed)");
+	      
+	      tmp = CDR_SAFE (tmp);
+
+	      /* this is repetitive but fast and simple */
+	      params[param_count] = QCsize;
+	      params[param_count+1] = Fplist_get (tmp, Qsize);
+	      if (!NILP (params[param_count+1])) param_count+=2;
+
+	      params[param_count] = QCtest;
+	      params[param_count+1] = Fplist_get (tmp, Qtest);
+	      if (!NILP (params[param_count+1])) param_count+=2;
+
+	      params[param_count] = QCweakness;
+	      params[param_count+1] = Fplist_get (tmp, Qweakness);
+	      if (!NILP (params[param_count+1])) param_count+=2;
+
+	      params[param_count] = QCrehash_size;
+	      params[param_count+1] = Fplist_get (tmp, Qrehash_size);
+	      if (!NILP (params[param_count+1])) param_count+=2;
+
+	      params[param_count] = QCrehash_threshold;
+	      params[param_count+1] = Fplist_get (tmp, Qrehash_threshold);
+	      if (!NILP (params[param_count+1])) param_count+=2;
+
+	      data = Fplist_get (tmp, Qdata); /* this is the hashtable data */
+
+	      /* now use params to make a new hashtable and fill it */
+	      Lisp_Object ht = Fmake_hash_table (param_count, params);
+	      Lisp_Object key = Qnil;
+	      
+	      while (CONSP (data))
+	      	{
+	      	  key = XCAR (data);
+	      	  data = XCDR (data);
+	      	  if (!CONSP (data))
+	      	    error ("Odd number of elements in hashtable data");
+	      	  val = XCAR (data);
+	      	  data = XCDR (data);
+	      	  Fputhash (key, val, ht);
+	      	}
+	      
+	      return ht;
+	    }
+	}
       if (c == '^')
 	{
 	  c = READCHAR;
@@ -4432,6 +4506,21 @@
 
   Vloads_in_progress = Qnil;
   staticpro (&Vloads_in_progress);
+
+  Qhash_table = intern ("hash-table");
+  staticpro (&Qhash_table);
+  Qdata = intern ("data");
+  staticpro (&Qdata);
+  Qtest = intern ("test");
+  staticpro (&Qtest);
+  Qsize = intern ("size");
+  staticpro (&Qsize);
+  Qweakness = intern ("weakness");
+  staticpro (&Qweakness);
+  Qrehash_size = intern ("rehash-size");
+  staticpro (&Qrehash_size);
+  Qrehash_threshold = intern ("rehash-threshold");
+  staticpro (&Qrehash_threshold);
 }
 
 /* arch-tag: a0d02733-0f96-4844-a659-9fd53c4f414d
Index: print.c
===================================================================
RCS file: /sources/emacs/emacs/src/print.c,v
retrieving revision 1.253
diff -u -r1.253 print.c
--- print.c	31 Jul 2008 05:33:53 -0000	1.253
+++ print.c	3 Dec 2008 19:17:59 -0000
@@ -1341,6 +1341,7 @@
  loop:
   if (STRINGP (obj) || CONSP (obj) || VECTORP (obj)
       || COMPILEDP (obj) || CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj)
+      || HASH_TABLE_P (obj)
       || (! NILP (Vprint_gensym)
 	  && SYMBOLP (obj)
 	  && !SYMBOL_INTERNED_P (obj)))
@@ -1536,6 +1537,7 @@
   /* Detect circularities and truncate them.  */
   if (STRINGP (obj) || CONSP (obj) || VECTORP (obj)
       || COMPILEDP (obj) || CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj)
+      || HASH_TABLE_P (obj)
       || (! NILP (Vprint_gensym)
 	  && SYMBOLP (obj)
 	  && !SYMBOL_INTERNED_P (obj)))
@@ -2036,6 +2038,7 @@
       else if (HASH_TABLE_P (obj))
 	{
 	  struct Lisp_Hash_Table *h = XHASH_TABLE (obj);
+#if 0
 	  strout ("#<hash-table", -1, -1, printcharfun, 0);
 	  if (SYMBOLP (h->test))
 	    {
@@ -2052,6 +2055,68 @@
 	  sprintf (buf, " 0x%lx", (unsigned long) h);
 	  strout (buf, -1, -1, printcharfun, 0);
 	  PRINTCHAR ('>');
+#endif
+	  /*
+	    implement a readable output, e.g.:
+	    #s(hash-table size 2 test equal data (k1 v1 k2 v2))
+	  */
+	  /* always print the size */
+	  sprintf (buf, "#s(hash-table size %ld", (long) XVECTOR (h->next)->size);
+	  strout (buf, -1, -1, printcharfun, 0);
+
+	  if (!NILP (h->test))
+	    {
+	      strout (" test ", -1, -1, printcharfun, 0);
+	      print_object (h->test, printcharfun, 0);
+	    }
+
+	  if (!NILP (h->weak))
+	    {
+	      strout (" weakness ", -1, -1, printcharfun, 0);
+	      print_object (h->weak, printcharfun, 0);
+	    }
+
+	  if (!NILP (h->rehash_size))
+	    {
+	      strout (" rehash-size ", -1, -1, printcharfun, 0);
+	      print_object (h->rehash_size, printcharfun, 0);
+	    }
+
+	  if (!NILP (h->rehash_threshold))
+	    {
+	      strout (" rehash-threshold ", -1, -1, printcharfun, 0);
+	      print_object (h->rehash_threshold, printcharfun, 0);
+	    }
+
+	  strout (" data ", -1, -1, printcharfun, 0);
+
+	  /* print the data here as a plist */
+	  int i;
+
+	  int real_size = HASH_TABLE_SIZE (h);
+	  int size = real_size;
+
+	  /* Don't print more elements than the specified maximum.  */
+	  if (NATNUMP (Vprint_length)
+	      && XFASTINT (Vprint_length) < size)
+	    size = XFASTINT (Vprint_length);
+	  
+	  PRINTCHAR ('(');
+	  for (i = 0; i < size; i++)
+	    if (!NILP (HASH_HASH (h, i)))
+	      {
+		if (i) PRINTCHAR (' ');
+		print_object (HASH_KEY (h, i), printcharfun, 0);
+		PRINTCHAR (' ');
+		print_object (HASH_VALUE (h, i), printcharfun, 0);
+	      }
+
+	  if (size < real_size)
+	    strout (" ...", 4, 4, printcharfun, 0);
+
+	  PRINTCHAR (')');
+	  PRINTCHAR (')');
+
 	}
       else if (BUFFERP (obj))
 	{

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-12-03 19:25                                                           ` Ted Zlatanov
@ 2008-12-04  2:05                                                             ` Stefan Monnier
  2008-12-04  6:23                                                               ` Stephen J. Turnbull
  2008-12-04 15:02                                                               ` Ted Zlatanov
  0 siblings, 2 replies; 86+ messages in thread
From: Stefan Monnier @ 2008-12-04  2:05 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

> I took your other suggestions, except I don't pass Qnil parameters to
> make-hash-table to keep things clean.  I hope this version of the patch
> is acceptable.

Some nitpicks, see below.
BTW, have you tried to delegate to some Elisp code?

> +	      /*
> +		Accept extended format for hashtables (extensible to
> +		other types), e.g.
> +		#s(hash-table size 2 test equal data (k1 v1 k2 v2))	     
> +	      */

We like to avoid putting comment markers on their own line.  So we'd write

	      /* Accept extended format for hashtables (extensible to
		 other types), e.g.
		 #s(hash-table size 2 test equal data (k1 v1 k2 v2))  */

> +	      /* 2 * number of allowed keywords to make-hash-table */

We like to terminate our comments like sentences: with a sot followed by
2 spaces.

> +	      if (!NILP (params[param_count+1])) param_count+=2;

We like to put the body of the `if' on a separate line.

> +	      data = Fplist_get (tmp, Qdata); /* this is the hashtable data */

Comments should be capitalized:  /* This is the hashtable data.  */

> +	      Lisp_Object ht = Fmake_hash_table (param_count, params);
> +	      Lisp_Object key = Qnil;

We recently decided it was OK to use ANSI C syntax for function headers,
but I don't think ANSI C allows such variable declarations in the middle
of a block.  So we should probably move the delcaration of those 2 vars
higher up, or open up a new block.

Other than that, it looks good.


        Stefan




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-12-04  2:05                                                             ` Stefan Monnier
@ 2008-12-04  6:23                                                               ` Stephen J. Turnbull
  2008-12-04  6:34                                                                 ` Miles Bader
  2008-12-04 15:02                                                               ` Ted Zlatanov
  1 sibling, 1 reply; 86+ messages in thread
From: Stephen J. Turnbull @ 2008-12-04  6:23 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Ted Zlatanov, emacs-devel

Stefan Monnier writes:

 > > +	      Lisp_Object ht = Fmake_hash_table (param_count, params);
 > > +	      Lisp_Object key = Qnil;
 > 
 > We recently decided it was OK to use ANSI C syntax for function headers,
 > but I don't think ANSI C allows such variable declarations in the middle
 > of a block.

ISTR that C99 does allow those declarations (which is a GoodThang[tm]
IMHO), but C89 definitely does not allow them (and portability is a
GooderThang[tm], so let's not do that).





^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-12-04  6:23                                                               ` Stephen J. Turnbull
@ 2008-12-04  6:34                                                                 ` Miles Bader
  2008-12-04  9:08                                                                   ` Andreas Schwab
  2008-12-04 13:18                                                                   ` Stefan Monnier
  0 siblings, 2 replies; 86+ messages in thread
From: Miles Bader @ 2008-12-04  6:34 UTC (permalink / raw)
  To: Stefan Monnier, emacs-devel

"Stephen J. Turnbull" <stephen@xemacs.org> writes:
>  > > +	      Lisp_Object ht = Fmake_hash_table (param_count, params);
>  > > +	      Lisp_Object key = Qnil;
>  > 
>  > We recently decided it was OK to use ANSI C syntax for function headers,
>  > but I don't think ANSI C allows such variable declarations in the middle
>  > of a block.
>
> ISTR that C99 does allow those declarations (which is a GoodThang[tm]
> IMHO), but C89 definitely does not allow them (and portability is a
> GooderThang[tm], so let's not do that).

BTW, is it now OK to use initializers with Lisp_Object variable declarations?

As I understand it, those used to be proscribed in emacs because they
didn't work correctly in some case (IIRC, some ancient IBM compiler
generated incorrect code), but enforcement has always been spotty, and I
expect the codebase is so chock full of such initializations now that
it's very unlikely it's really still a problem...

-Miles

-- 
Suburbia: where they tear out the trees and then name streets after them.




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-12-04  6:34                                                                 ` Miles Bader
@ 2008-12-04  9:08                                                                   ` Andreas Schwab
  2008-12-04 13:18                                                                   ` Stefan Monnier
  1 sibling, 0 replies; 86+ messages in thread
From: Andreas Schwab @ 2008-12-04  9:08 UTC (permalink / raw)
  To: Miles Bader; +Cc: Stefan Monnier, emacs-devel

Miles Bader <miles@gnu.org> writes:

> BTW, is it now OK to use initializers with Lisp_Object variable declarations?

This was never a problem, Lisp_Object is just an integer (if you make it
a union you need to compile with a good compiler anyway).

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
PGP key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-12-04  6:34                                                                 ` Miles Bader
  2008-12-04  9:08                                                                   ` Andreas Schwab
@ 2008-12-04 13:18                                                                   ` Stefan Monnier
  1 sibling, 0 replies; 86+ messages in thread
From: Stefan Monnier @ 2008-12-04 13:18 UTC (permalink / raw)
  To: Miles Bader; +Cc: emacs-devel

> BTW, is it now OK to use initializers with Lisp_Object variable declarations?

Yes,


        Stefan




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-12-04  2:05                                                             ` Stefan Monnier
  2008-12-04  6:23                                                               ` Stephen J. Turnbull
@ 2008-12-04 15:02                                                               ` Ted Zlatanov
  2008-12-04 19:34                                                                 ` Stefan Monnier
  2009-07-30 18:24                                                                 ` Ted Zlatanov
  1 sibling, 2 replies; 86+ messages in thread
From: Ted Zlatanov @ 2008-12-04 15:02 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1135 bytes --]

On Wed, 03 Dec 2008 21:05:54 -0500 Stefan Monnier <monnier@iro.umontreal.ca> wrote: 

>> I took your other suggestions, except I don't pass Qnil parameters to
>> make-hash-table to keep things clean.  I hope this version of the patch
>> is acceptable.

SM> Some nitpicks, see below.
SM> BTW, have you tried to delegate to some Elisp code?

Why at this point?  The C code is written, is there a problem with it?

SM> We like to avoid putting comment markers on their own line.  We like
SM> to terminate our comments like sentences: with a [d]ot followed by 2
SM> spaces.  We like to put the body of the `if' on a separate line.
SM> Comments should be capitalized.

All these are fixed, thanks for pointing them out.

>> +	      Lisp_Object ht = Fmake_hash_table (param_count, params);
>> +	      Lisp_Object key = Qnil;

SM> We recently decided it was OK to use ANSI C syntax for function headers,
SM> but I don't think ANSI C allows such variable declarations in the middle
SM> of a block.  So we should probably move the delcaration of those 2 vars
SM> higher up, or open up a new block.

Fixed.  Revised patch attached.

Thanks
Ted


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: hashprint.patch --]
[-- Type: text/x-diff, Size: 6615 bytes --]

? hashprint.patch
Index: lread.c
===================================================================
RCS file: /sources/emacs/emacs/src/lread.c,v
retrieving revision 1.401
diff -u -r1.401 lread.c
--- lread.c	7 Sep 2008 20:41:10 -0000	1.401
+++ lread.c	4 Dec 2008 15:02:39 -0000
@@ -80,6 +80,14 @@
 extern int errno;
 #endif
 
+/* hash table read constants */
+Lisp_Object Qhash_table, Qdata;
+Lisp_Object Qtest, Qsize;
+Lisp_Object Qweakness;
+Lisp_Object Qrehash_size;
+Lisp_Object Qrehash_threshold;
+extern Lisp_Object QCtest, QCsize, QCrehash_size, QCrehash_threshold, QCweakness;
+
 Lisp_Object Qread_char, Qget_file_char, Qstandard_input, Qcurrent_load_list;
 Lisp_Object Qvariable_documentation, Vvalues, Vstandard_input, Vafter_load_alist;
 Lisp_Object Qascii_character, Qload, Qload_file_name;
@@ -2341,6 +2349,78 @@
 
     case '#':
       c = READCHAR;
+      if (c == 's')
+	{
+	  c = READCHAR;
+	  if (c == '(')
+	    {
+	      /* Accept extended format for hashtables (extensible to
+		 other types), e.g.
+		 #s(hash-table size 2 test equal data (k1 v1 k2 v2)) */
+	      Lisp_Object tmp = read_list (0, readcharfun);
+	      Lisp_Object head = CAR_SAFE (tmp);
+	      Lisp_Object data = Qnil;
+	      Lisp_Object val = Qnil;
+	      /* The size is 2 * number of allowed keywords to
+		 make-hash-table. */
+	      Lisp_Object params[10]; 
+	      Lisp_Object ht;
+	      Lisp_Object key = Qnil;
+	      int param_count = 0;
+	      int i;
+	      
+	      if (!EQ (head, Qhash_table))
+		error ("Invalid extended read marker at head of #s list "
+		       "(only hash-table allowed)");
+	      
+	      tmp = CDR_SAFE (tmp);
+
+	      /* This is repetitive but fast and simple. */
+	      params[param_count] = QCsize;
+	      params[param_count+1] = Fplist_get (tmp, Qsize);
+	      if (!NILP (params[param_count+1]))
+		param_count+=2;
+
+	      params[param_count] = QCtest;
+	      params[param_count+1] = Fplist_get (tmp, Qtest);
+	      if (!NILP (params[param_count+1]))
+		param_count+=2;
+
+	      params[param_count] = QCweakness;
+	      params[param_count+1] = Fplist_get (tmp, Qweakness);
+	      if (!NILP (params[param_count+1]))
+		param_count+=2;
+
+	      params[param_count] = QCrehash_size;
+	      params[param_count+1] = Fplist_get (tmp, Qrehash_size);
+	      if (!NILP (params[param_count+1]))
+		param_count+=2;
+
+	      params[param_count] = QCrehash_threshold;
+	      params[param_count+1] = Fplist_get (tmp, Qrehash_threshold);
+	      if (!NILP (params[param_count+1]))
+		param_count+=2;
+
+	      /* This is the hashtable data. */
+	      data = Fplist_get (tmp, Qdata);
+
+	      /* Now use params to make a new hashtable and fill it. */
+	      ht = Fmake_hash_table (param_count, params);
+	      
+	      while (CONSP (data))
+	      	{
+	      	  key = XCAR (data);
+	      	  data = XCDR (data);
+	      	  if (!CONSP (data))
+	      	    error ("Odd number of elements in hashtable data");
+	      	  val = XCAR (data);
+	      	  data = XCDR (data);
+	      	  Fputhash (key, val, ht);
+	      	}
+	      
+	      return ht;
+	    }
+	}
       if (c == '^')
 	{
 	  c = READCHAR;
@@ -4432,6 +4512,21 @@
 
   Vloads_in_progress = Qnil;
   staticpro (&Vloads_in_progress);
+
+  Qhash_table = intern ("hash-table");
+  staticpro (&Qhash_table);
+  Qdata = intern ("data");
+  staticpro (&Qdata);
+  Qtest = intern ("test");
+  staticpro (&Qtest);
+  Qsize = intern ("size");
+  staticpro (&Qsize);
+  Qweakness = intern ("weakness");
+  staticpro (&Qweakness);
+  Qrehash_size = intern ("rehash-size");
+  staticpro (&Qrehash_size);
+  Qrehash_threshold = intern ("rehash-threshold");
+  staticpro (&Qrehash_threshold);
 }
 
 /* arch-tag: a0d02733-0f96-4844-a659-9fd53c4f414d
Index: print.c
===================================================================
RCS file: /sources/emacs/emacs/src/print.c,v
retrieving revision 1.253
diff -u -r1.253 print.c
--- print.c	31 Jul 2008 05:33:53 -0000	1.253
+++ print.c	4 Dec 2008 15:02:39 -0000
@@ -1341,6 +1341,7 @@
  loop:
   if (STRINGP (obj) || CONSP (obj) || VECTORP (obj)
       || COMPILEDP (obj) || CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj)
+      || HASH_TABLE_P (obj)
       || (! NILP (Vprint_gensym)
 	  && SYMBOLP (obj)
 	  && !SYMBOL_INTERNED_P (obj)))
@@ -1536,6 +1537,7 @@
   /* Detect circularities and truncate them.  */
   if (STRINGP (obj) || CONSP (obj) || VECTORP (obj)
       || COMPILEDP (obj) || CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj)
+      || HASH_TABLE_P (obj)
       || (! NILP (Vprint_gensym)
 	  && SYMBOLP (obj)
 	  && !SYMBOL_INTERNED_P (obj)))
@@ -2036,6 +2038,7 @@
       else if (HASH_TABLE_P (obj))
 	{
 	  struct Lisp_Hash_Table *h = XHASH_TABLE (obj);
+#if 0
 	  strout ("#<hash-table", -1, -1, printcharfun, 0);
 	  if (SYMBOLP (h->test))
 	    {
@@ -2052,6 +2055,67 @@
 	  sprintf (buf, " 0x%lx", (unsigned long) h);
 	  strout (buf, -1, -1, printcharfun, 0);
 	  PRINTCHAR ('>');
+#endif
+	  /* Implement a readable output, e.g.:
+	    #s(hash-table size 2 test equal data (k1 v1 k2 v2)) */
+	  /* Always print the size. */
+	  sprintf (buf, "#s(hash-table size %ld",
+		   (long) XVECTOR (h->next)->size);
+	  strout (buf, -1, -1, printcharfun, 0);
+
+	  if (!NILP (h->test))
+	    {
+	      strout (" test ", -1, -1, printcharfun, 0);
+	      print_object (h->test, printcharfun, 0);
+	    }
+
+	  if (!NILP (h->weak))
+	    {
+	      strout (" weakness ", -1, -1, printcharfun, 0);
+	      print_object (h->weak, printcharfun, 0);
+	    }
+
+	  if (!NILP (h->rehash_size))
+	    {
+	      strout (" rehash-size ", -1, -1, printcharfun, 0);
+	      print_object (h->rehash_size, printcharfun, 0);
+	    }
+
+	  if (!NILP (h->rehash_threshold))
+	    {
+	      strout (" rehash-threshold ", -1, -1, printcharfun, 0);
+	      print_object (h->rehash_threshold, printcharfun, 0);
+	    }
+
+	  strout (" data ", -1, -1, printcharfun, 0);
+
+	  /* Print the data here as a plist. */
+	  int i;
+
+	  int real_size = HASH_TABLE_SIZE (h);
+	  int size = real_size;
+
+	  /* Don't print more elements than the specified maximum.  */
+	  if (NATNUMP (Vprint_length)
+	      && XFASTINT (Vprint_length) < size)
+	    size = XFASTINT (Vprint_length);
+	  
+	  PRINTCHAR ('(');
+	  for (i = 0; i < size; i++)
+	    if (!NILP (HASH_HASH (h, i)))
+	      {
+		if (i) PRINTCHAR (' ');
+		print_object (HASH_KEY (h, i), printcharfun, 0);
+		PRINTCHAR (' ');
+		print_object (HASH_VALUE (h, i), printcharfun, 0);
+	      }
+
+	  if (size < real_size)
+	    strout (" ...", 4, 4, printcharfun, 0);
+
+	  PRINTCHAR (')');
+	  PRINTCHAR (')');
+
 	}
       else if (BUFFERP (obj))
 	{

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-12-04 15:02                                                               ` Ted Zlatanov
@ 2008-12-04 19:34                                                                 ` Stefan Monnier
  2008-12-04 19:57                                                                   ` Ted Zlatanov
  2009-07-30 18:24                                                                 ` Ted Zlatanov
  1 sibling, 1 reply; 86+ messages in thread
From: Stefan Monnier @ 2008-12-04 19:34 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

SM> BTW, have you tried to delegate to some Elisp code?
> Why at this point?  The C code is written, is there a problem with it?

No problem with it, just curious.

> Fixed.  Revised patch attached.

Thank you.  Looks good.


        Stefan




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-12-04 19:34                                                                 ` Stefan Monnier
@ 2008-12-04 19:57                                                                   ` Ted Zlatanov
  0 siblings, 0 replies; 86+ messages in thread
From: Ted Zlatanov @ 2008-12-04 19:57 UTC (permalink / raw)
  To: emacs-devel

On Thu, 04 Dec 2008 14:34:23 -0500 Stefan Monnier <monnier@IRO.UMontreal.CA> wrote: 

SM> BTW, have you tried to delegate to some Elisp code?
>> Why at this point?  The C code is written, is there a problem with it?

SM> No problem with it, just curious.

I wanted to learn a bit about the Emacs internals, now and for the
future.  Also the C code is probably going to be a little faster.

(let's not forget my LOC stats shot up too :)

Ted





^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2008-12-04 15:02                                                               ` Ted Zlatanov
  2008-12-04 19:34                                                                 ` Stefan Monnier
@ 2009-07-30 18:24                                                                 ` Ted Zlatanov
  2009-07-30 19:08                                                                   ` Chong Yidong
  1 sibling, 1 reply; 86+ messages in thread
From: Ted Zlatanov @ 2009-07-30 18:24 UTC (permalink / raw)
  To: emacs-devel

On Thu, 04 Dec 2008 09:02:56 -0600 Ted Zlatanov <tzz@lifelogs.com> wrote: 

TZ> Fixed.  Revised patch attached.

Hi,

I would like to commit and start using the hashtable print/read support
I proposed last December.  

The Gnus registry is my first target since I control that code.  My
question is, what's the right way to tell applications that hashtable
print/read support is available?  Is it with featurep and provide?  If
so, what name should I use and where do I put the provide statement
(looks like lisp/bindings.el from a quick look)?

I'll add that change to the patch, verify it works against the CVS
trunk, and resubmit for a final review.

Thanks
Ted





^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2009-07-30 18:24                                                                 ` Ted Zlatanov
@ 2009-07-30 19:08                                                                   ` Chong Yidong
  2009-07-30 19:22                                                                     ` Ted Zlatanov
  0 siblings, 1 reply; 86+ messages in thread
From: Chong Yidong @ 2009-07-30 19:08 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

Ted Zlatanov <tzz@lifelogs.com> writes:

> The Gnus registry is my first target since I control that code.  My
> question is, what's the right way to tell applications that hashtable
> print/read support is available?  Is it with featurep and provide?  If
> so, what name should I use and where do I put the provide statement
> (looks like lisp/bindings.el from a quick look)?

Put the `provide' call in whichever file the code for the hastable
print/read support resides (which I guess will be one of the C files).




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2009-07-30 19:08                                                                   ` Chong Yidong
@ 2009-07-30 19:22                                                                     ` Ted Zlatanov
  2009-07-30 19:40                                                                       ` Chong Yidong
  0 siblings, 1 reply; 86+ messages in thread
From: Ted Zlatanov @ 2009-07-30 19:22 UTC (permalink / raw)
  To: emacs-devel

On Thu, 30 Jul 2009 15:08:01 -0400 Chong Yidong <cyd@stupidchicken.com> wrote: 

CY> Ted Zlatanov <tzz@lifelogs.com> writes:
>> The Gnus registry is my first target since I control that code.  My
>> question is, what's the right way to tell applications that hashtable
>> print/read support is available?  Is it with featurep and provide?  If
>> so, what name should I use and where do I put the provide statement
>> (looks like lisp/bindings.el from a quick look)?

CY> Put the `provide' call in whichever file the code for the hastable
CY> print/read support resides (which I guess will be one of the C files).

OK.  Can I use two names: "hashtable-read" and "hashtable-print" for the
feature?  I can't think of a single name that doesn't sound clumsy
(suggestions welcome, of course).

Ted





^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2009-07-30 19:22                                                                     ` Ted Zlatanov
@ 2009-07-30 19:40                                                                       ` Chong Yidong
  2009-07-30 21:04                                                                         ` Stefan Monnier
  0 siblings, 1 reply; 86+ messages in thread
From: Chong Yidong @ 2009-07-30 19:40 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

Ted Zlatanov <tzz@lifelogs.com> writes:

> OK.  Can I use two names: "hashtable-read" and "hashtable-print" for the
> feature?  I can't think of a single name that doesn't sound clumsy
> (suggestions welcome, of course).

Just hashtable-read, I think.  After all, hashtables already have a
print representation (all Lisp objects do)---the present difficulty is
that this print representation isn't readable.




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2009-07-30 19:40                                                                       ` Chong Yidong
@ 2009-07-30 21:04                                                                         ` Stefan Monnier
  2009-07-31  1:30                                                                           ` Stefan Monnier
  2009-07-31 18:10                                                                           ` Ted Zlatanov
  0 siblings, 2 replies; 86+ messages in thread
From: Stefan Monnier @ 2009-07-30 21:04 UTC (permalink / raw)
  To: Chong Yidong; +Cc: Ted Zlatanov, emacs-devel

>> OK.  Can I use two names: "hashtable-read" and "hashtable-print" for the
>> feature?  I can't think of a single name that doesn't sound clumsy
>> (suggestions welcome, of course).

> Just hashtable-read, I think.  After all, hashtables already have a
> print representation (all Lisp objects do)---the present difficulty is
> that this print representation isn't readable.

Or hashtable-print-readable.


        Stefan




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2009-07-30 21:04                                                                         ` Stefan Monnier
@ 2009-07-31  1:30                                                                           ` Stefan Monnier
  2009-07-31 17:49                                                                             ` Ted Zlatanov
  2009-07-31 18:10                                                                           ` Ted Zlatanov
  1 sibling, 1 reply; 86+ messages in thread
From: Stefan Monnier @ 2009-07-31  1:30 UTC (permalink / raw)
  To: Chong Yidong; +Cc: Ted Zlatanov, emacs-devel

>>> OK.  Can I use two names: "hashtable-read" and "hashtable-print" for the
>>> feature?  I can't think of a single name that doesn't sound clumsy
>>> (suggestions welcome, of course).

>> Just hashtable-read, I think.  After all, hashtables already have a
>> print representation (all Lisp objects do)---the present difficulty is
>> that this print representation isn't readable.

> Or hashtable-print-readable.

Of, course there's always another (more reliable) way:

   (hash-table-p (read-from-string (prin1-to-string (make-hash-table))))


-- Stefan




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2009-07-31  1:30                                                                           ` Stefan Monnier
@ 2009-07-31 17:49                                                                             ` Ted Zlatanov
  2009-07-31 19:03                                                                               ` Stefan Monnier
  0 siblings, 1 reply; 86+ messages in thread
From: Ted Zlatanov @ 2009-07-31 17:49 UTC (permalink / raw)
  To: emacs-devel

On Thu, 30 Jul 2009 21:30:48 -0400 Stefan Monnier <monnier@iro.umontreal.ca> wrote: 

>>>> OK.  Can I use two names: "hashtable-read" and "hashtable-print" for the
>>>> feature?  I can't think of a single name that doesn't sound clumsy
>>>> (suggestions welcome, of course).

>>> Just hashtable-read, I think.  After all, hashtables already have a
>>> print representation (all Lisp objects do)---the present difficulty is
>>> that this print representation isn't readable.

>> Or hashtable-print-readable.

SM> Of, course there's always another (more reliable) way:

SM>    (hash-table-p (read-from-string (prin1-to-string (make-hash-table))))

That was my first thought, but it seemed like a really hacky approach
when featurep exists.

Ted





^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2009-07-30 21:04                                                                         ` Stefan Monnier
  2009-07-31  1:30                                                                           ` Stefan Monnier
@ 2009-07-31 18:10                                                                           ` Ted Zlatanov
  1 sibling, 0 replies; 86+ messages in thread
From: Ted Zlatanov @ 2009-07-31 18:10 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 604 bytes --]

On Thu, 30 Jul 2009 17:04:22 -0400 Stefan Monnier <monnier@IRO.UMontreal.CA> wrote: 

>>> OK.  Can I use two names: "hashtable-read" and "hashtable-print" for the
>>> feature?  I can't think of a single name that doesn't sound clumsy
>>> (suggestions welcome, of course).

>> Just hashtable-read, I think.  After all, hashtables already have a
>> print representation (all Lisp objects do)---the present difficulty is
>> that this print representation isn't readable.

SM> Or hashtable-print-readable.

Attached is the patch for review.  I've been using it for a while with
no issues, FWIW.

Thanks
Ted


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: hashprint.patch --]
[-- Type: text/x-diff, Size: 7453 bytes --]

? hashprint.patch
Index: lread.c
===================================================================
RCS file: /sources/emacs/emacs/src/lread.c,v
retrieving revision 1.406
diff -c -r1.406 lread.c
*** lread.c	29 Apr 2009 03:03:00 -0000	1.406
--- lread.c	31 Jul 2009 18:09:25 -0000
***************
*** 80,85 ****
--- 80,93 ----
  extern int errno;
  #endif
  
+ /* hash table read constants */
+ Lisp_Object Qhash_table, Qdata;
+ Lisp_Object Qtest, Qsize;
+ Lisp_Object Qweakness;
+ Lisp_Object Qrehash_size;
+ Lisp_Object Qrehash_threshold;
+ extern Lisp_Object QCtest, QCsize, QCrehash_size, QCrehash_threshold, QCweakness;
+ 
  Lisp_Object Qread_char, Qget_file_char, Qstandard_input, Qcurrent_load_list;
  Lisp_Object Qvariable_documentation, Vvalues, Vstandard_input, Vafter_load_alist;
  Lisp_Object Qascii_character, Qload, Qload_file_name;
***************
*** 2341,2346 ****
--- 2349,2426 ----
  
      case '#':
        c = READCHAR;
+       if (c == 's')
+ 	{
+ 	  c = READCHAR;
+ 	  if (c == '(')
+ 	    {
+ 	      /* Accept extended format for hashtables (extensible to
+ 		 other types), e.g.
+ 		 #s(hash-table size 2 test equal data (k1 v1 k2 v2)) */
+ 	      Lisp_Object tmp = read_list (0, readcharfun);
+ 	      Lisp_Object head = CAR_SAFE (tmp);
+ 	      Lisp_Object data = Qnil;
+ 	      Lisp_Object val = Qnil;
+ 	      /* The size is 2 * number of allowed keywords to
+ 		 make-hash-table. */
+ 	      Lisp_Object params[10]; 
+ 	      Lisp_Object ht;
+ 	      Lisp_Object key = Qnil;
+ 	      int param_count = 0;
+ 	      int i;
+ 	      
+ 	      if (!EQ (head, Qhash_table))
+ 		error ("Invalid extended read marker at head of #s list "
+ 		       "(only hash-table allowed)");
+ 	      
+ 	      tmp = CDR_SAFE (tmp);
+ 
+ 	      /* This is repetitive but fast and simple. */
+ 	      params[param_count] = QCsize;
+ 	      params[param_count+1] = Fplist_get (tmp, Qsize);
+ 	      if (!NILP (params[param_count+1]))
+ 		param_count+=2;
+ 
+ 	      params[param_count] = QCtest;
+ 	      params[param_count+1] = Fplist_get (tmp, Qtest);
+ 	      if (!NILP (params[param_count+1]))
+ 		param_count+=2;
+ 
+ 	      params[param_count] = QCweakness;
+ 	      params[param_count+1] = Fplist_get (tmp, Qweakness);
+ 	      if (!NILP (params[param_count+1]))
+ 		param_count+=2;
+ 
+ 	      params[param_count] = QCrehash_size;
+ 	      params[param_count+1] = Fplist_get (tmp, Qrehash_size);
+ 	      if (!NILP (params[param_count+1]))
+ 		param_count+=2;
+ 
+ 	      params[param_count] = QCrehash_threshold;
+ 	      params[param_count+1] = Fplist_get (tmp, Qrehash_threshold);
+ 	      if (!NILP (params[param_count+1]))
+ 		param_count+=2;
+ 
+ 	      /* This is the hashtable data. */
+ 	      data = Fplist_get (tmp, Qdata);
+ 
+ 	      /* Now use params to make a new hashtable and fill it. */
+ 	      ht = Fmake_hash_table (param_count, params);
+ 	      
+ 	      while (CONSP (data))
+ 	      	{
+ 	      	  key = XCAR (data);
+ 	      	  data = XCDR (data);
+ 	      	  if (!CONSP (data))
+ 	      	    error ("Odd number of elements in hashtable data");
+ 	      	  val = XCAR (data);
+ 	      	  data = XCDR (data);
+ 	      	  Fputhash (key, val, ht);
+ 	      	}
+ 	      
+ 	      return ht;
+ 	    }
+ 	}
        if (c == '^')
  	{
  	  c = READCHAR;
***************
*** 4436,4441 ****
--- 4516,4536 ----
  
    Vloads_in_progress = Qnil;
    staticpro (&Vloads_in_progress);
+ 
+   Qhash_table = intern ("hash-table");
+   staticpro (&Qhash_table);
+   Qdata = intern ("data");
+   staticpro (&Qdata);
+   Qtest = intern ("test");
+   staticpro (&Qtest);
+   Qsize = intern ("size");
+   staticpro (&Qsize);
+   Qweakness = intern ("weakness");
+   staticpro (&Qweakness);
+   Qrehash_size = intern ("rehash-size");
+   staticpro (&Qrehash_size);
+   Qrehash_threshold = intern ("rehash-threshold");
+   staticpro (&Qrehash_threshold);
  }
  
  /* arch-tag: a0d02733-0f96-4844-a659-9fd53c4f414d
Index: print.c
===================================================================
RCS file: /sources/emacs/emacs/src/print.c,v
retrieving revision 1.256
diff -c -r1.256 print.c
*** print.c	3 Apr 2009 06:23:49 -0000	1.256
--- print.c	31 Jul 2009 18:09:25 -0000
***************
*** 1341,1346 ****
--- 1341,1347 ----
   loop:
    if (STRINGP (obj) || CONSP (obj) || VECTORP (obj)
        || COMPILEDP (obj) || CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj)
+       || HASH_TABLE_P (obj)
        || (! NILP (Vprint_gensym)
  	  && SYMBOLP (obj)
  	  && !SYMBOL_INTERNED_P (obj)))
***************
*** 1536,1541 ****
--- 1537,1543 ----
    /* Detect circularities and truncate them.  */
    if (STRINGP (obj) || CONSP (obj) || VECTORP (obj)
        || COMPILEDP (obj) || CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj)
+       || HASH_TABLE_P (obj)
        || (! NILP (Vprint_gensym)
  	  && SYMBOLP (obj)
  	  && !SYMBOL_INTERNED_P (obj)))
***************
*** 2031,2036 ****
--- 2033,2039 ----
        else if (HASH_TABLE_P (obj))
  	{
  	  struct Lisp_Hash_Table *h = XHASH_TABLE (obj);
+ #if 0
  	  strout ("#<hash-table", -1, -1, printcharfun, 0);
  	  if (SYMBOLP (h->test))
  	    {
***************
*** 2047,2052 ****
--- 2050,2116 ----
  	  sprintf (buf, " 0x%lx", (unsigned long) h);
  	  strout (buf, -1, -1, printcharfun, 0);
  	  PRINTCHAR ('>');
+ #endif
+ 	  /* Implement a readable output, e.g.:
+ 	    #s(hash-table size 2 test equal data (k1 v1 k2 v2)) */
+ 	  /* Always print the size. */
+ 	  sprintf (buf, "#s(hash-table size %ld",
+ 		   (long) XVECTOR (h->next)->size);
+ 	  strout (buf, -1, -1, printcharfun, 0);
+ 
+ 	  if (!NILP (h->test))
+ 	    {
+ 	      strout (" test ", -1, -1, printcharfun, 0);
+ 	      print_object (h->test, printcharfun, 0);
+ 	    }
+ 
+ 	  if (!NILP (h->weak))
+ 	    {
+ 	      strout (" weakness ", -1, -1, printcharfun, 0);
+ 	      print_object (h->weak, printcharfun, 0);
+ 	    }
+ 
+ 	  if (!NILP (h->rehash_size))
+ 	    {
+ 	      strout (" rehash-size ", -1, -1, printcharfun, 0);
+ 	      print_object (h->rehash_size, printcharfun, 0);
+ 	    }
+ 
+ 	  if (!NILP (h->rehash_threshold))
+ 	    {
+ 	      strout (" rehash-threshold ", -1, -1, printcharfun, 0);
+ 	      print_object (h->rehash_threshold, printcharfun, 0);
+ 	    }
+ 
+ 	  strout (" data ", -1, -1, printcharfun, 0);
+ 
+ 	  /* Print the data here as a plist. */
+ 	  int i;
+ 
+ 	  int real_size = HASH_TABLE_SIZE (h);
+ 	  int size = real_size;
+ 
+ 	  /* Don't print more elements than the specified maximum.  */
+ 	  if (NATNUMP (Vprint_length)
+ 	      && XFASTINT (Vprint_length) < size)
+ 	    size = XFASTINT (Vprint_length);
+ 	  
+ 	  PRINTCHAR ('(');
+ 	  for (i = 0; i < size; i++)
+ 	    if (!NILP (HASH_HASH (h, i)))
+ 	      {
+ 		if (i) PRINTCHAR (' ');
+ 		print_object (HASH_KEY (h, i), printcharfun, 0);
+ 		PRINTCHAR (' ');
+ 		print_object (HASH_VALUE (h, i), printcharfun, 0);
+ 	      }
+ 
+ 	  if (size < real_size)
+ 	    strout (" ...", 4, 4, printcharfun, 0);
+ 
+ 	  PRINTCHAR (')');
+ 	  PRINTCHAR (')');
+ 
  	}
        else if (BUFFERP (obj))
  	{
***************
*** 2354,2359 ****
--- 2418,2425 ----
    Qfloat_output_format = intern ("float-output-format");
    staticpro (&Qfloat_output_format);
  
+   Fprovide (intern ("hashtable-print-readable"), Qnil);
+   
    DEFVAR_LISP ("print-length", &Vprint_length,
  	       doc: /* Maximum length of list to print before abbreviating.
  A value of nil means no limit.  See also `eval-expression-print-length'.  */);

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2009-07-31 17:49                                                                             ` Ted Zlatanov
@ 2009-07-31 19:03                                                                               ` Stefan Monnier
  2009-07-31 20:25                                                                                 ` Ted Zlatanov
  0 siblings, 1 reply; 86+ messages in thread
From: Stefan Monnier @ 2009-07-31 19:03 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

SM> Of, course there's always another (more reliable) way:
SM> (hash-table-p (read-from-string (prin1-to-string (make-hash-table))))
> That was my first thought, but it seemed like a really hacky approach
> when featurep exists.

It's definitely not hacky.  It's more reliable (tho it probably requires
a bit of fiddling such as wrapping it in ignore-errors) and tests more
directly the presence of the feature you need.

The advantage of the featurep call is that it's likely to be
more efficient (which only matters if the test is made within a loop,
of course).


        Stefan




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2009-07-31 19:03                                                                               ` Stefan Monnier
@ 2009-07-31 20:25                                                                                 ` Ted Zlatanov
  2009-08-01  2:22                                                                                   ` Stephen J. Turnbull
                                                                                                     ` (2 more replies)
  0 siblings, 3 replies; 86+ messages in thread
From: Ted Zlatanov @ 2009-07-31 20:25 UTC (permalink / raw)
  To: emacs-devel

On Fri, 31 Jul 2009 15:03:48 -0400 Stefan Monnier <monnier@iro.umontreal.ca> wrote: 

SM> Of, course there's always another (more reliable) way:
SM> (hash-table-p (read-from-string (prin1-to-string (make-hash-table))))
...
SM> It's definitely not hacky.  It's more reliable (tho it probably requires
SM> a bit of fiddling such as wrapping it in ignore-errors) and tests more
SM> directly the presence of the feature you need.

SM> The advantage of the featurep call is that it's likely to be
SM> more efficient (which only matters if the test is made within a loop,
SM> of course).

If it's all right, can I stick to provide/featurep?  It simplifies the
client code, plus there are some performance improvements as you noted.

Ted





^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2009-07-31 20:25                                                                                 ` Ted Zlatanov
@ 2009-08-01  2:22                                                                                   ` Stephen J. Turnbull
  2009-08-01 11:35                                                                                   ` Chong Yidong
  2009-08-03 21:23                                                                                   ` Stefan Monnier
  2 siblings, 0 replies; 86+ messages in thread
From: Stephen J. Turnbull @ 2009-08-01  2:22 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

Ted Zlatanov writes:
 > On Fri, 31 Jul 2009 15:03:48 -0400 Stefan Monnier <monnier@iro.umontreal.ca> wrote: 
 > 
 > SM> Of, course there's always another (more reliable) way:
 > SM> (hash-table-p (read-from-string (prin1-to-string (make-hash-table))))

 > If it's all right, can I stick to provide/featurep?  It simplifies the
 > client code, plus there are some performance improvements as you noted.

Durn.  And here I was hoping this would eventually turn into a
full-blown replacement for Autoconf.




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2009-07-31 20:25                                                                                 ` Ted Zlatanov
  2009-08-01  2:22                                                                                   ` Stephen J. Turnbull
@ 2009-08-01 11:35                                                                                   ` Chong Yidong
  2009-08-03 14:53                                                                                     ` Ted Zlatanov
  2009-08-03 21:23                                                                                   ` Stefan Monnier
  2 siblings, 1 reply; 86+ messages in thread
From: Chong Yidong @ 2009-08-01 11:35 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

Ted Zlatanov <tzz@lifelogs.com> writes:

> If it's all right, can I stick to provide/featurep?  It simplifies the
> client code, plus there are some performance improvements as you noted.

Yes, please use `provide'.




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2009-08-01 11:35                                                                                   ` Chong Yidong
@ 2009-08-03 14:53                                                                                     ` Ted Zlatanov
  2009-08-05  9:20                                                                                       ` Ted Zlatanov
  0 siblings, 1 reply; 86+ messages in thread
From: Ted Zlatanov @ 2009-08-03 14:53 UTC (permalink / raw)
  To: emacs-devel

On Sat, 01 Aug 2009 07:35:44 -0400 Chong Yidong <cyd@stupidchicken.com> wrote: 

CY> Ted Zlatanov <tzz@lifelogs.com> writes:
>> If it's all right, can I stick to provide/featurep?  It simplifies the
>> client code, plus there are some performance improvements as you noted.

CY> Yes, please use `provide'.

In that case the patch is fine as is.  Can you please commit it if it is
all right, or let me know and I'll commit it?

Thanks
Ted





^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2009-07-31 20:25                                                                                 ` Ted Zlatanov
  2009-08-01  2:22                                                                                   ` Stephen J. Turnbull
  2009-08-01 11:35                                                                                   ` Chong Yidong
@ 2009-08-03 21:23                                                                                   ` Stefan Monnier
  2 siblings, 0 replies; 86+ messages in thread
From: Stefan Monnier @ 2009-08-03 21:23 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

> If it's all right, can I stick to provide/featurep?

Of course.  I was just pointing out that the other option is not a hack.


        Stefan





^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2009-08-03 14:53                                                                                     ` Ted Zlatanov
@ 2009-08-05  9:20                                                                                       ` Ted Zlatanov
  2009-08-05 13:48                                                                                         ` Chong Yidong
                                                                                                           ` (2 more replies)
  0 siblings, 3 replies; 86+ messages in thread
From: Ted Zlatanov @ 2009-08-05  9:20 UTC (permalink / raw)
  To: emacs-devel

On Mon, 03 Aug 2009 09:53:38 -0500 Ted Zlatanov <tzz@lifelogs.com> wrote: 

TZ> On Sat, 01 Aug 2009 07:35:44 -0400 Chong Yidong <cyd@stupidchicken.com> wrote: 
CY> Ted Zlatanov <tzz@lifelogs.com> writes:
>>> If it's all right, can I stick to provide/featurep?  It simplifies the
>>> client code, plus there are some performance improvements as you noted.

CY> Yes, please use `provide'.

TZ> In that case the patch is fine as is.  Can you please commit it if it is
TZ> all right, or let me know and I'll commit it?

I've committed the patch with the usual ChangeLog information.

Ted





^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2009-08-05  9:20                                                                                       ` Ted Zlatanov
@ 2009-08-05 13:48                                                                                         ` Chong Yidong
  2009-08-05 16:48                                                                                           ` Ted Zlatanov
  2009-08-06 10:13                                                                                         ` Dan Nicolaescu
  2009-08-06 16:58                                                                                         ` Florian Beck
  2 siblings, 1 reply; 86+ messages in thread
From: Chong Yidong @ 2009-08-05 13:48 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

Ted Zlatanov <tzz@lifelogs.com> writes:

> I've committed the patch with the usual ChangeLog information.

Please add a NEWS entry as well.




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2009-08-05 13:48                                                                                         ` Chong Yidong
@ 2009-08-05 16:48                                                                                           ` Ted Zlatanov
  2009-08-06 16:30                                                                                             ` Stefan Monnier
  0 siblings, 1 reply; 86+ messages in thread
From: Ted Zlatanov @ 2009-08-05 16:48 UTC (permalink / raw)
  To: emacs-devel

On Wed, 05 Aug 2009 09:48:43 -0400 Chong Yidong <cyd@stupidchicken.com> wrote: 

CY> Ted Zlatanov <tzz@lifelogs.com> writes:
>> I've committed the patch with the usual ChangeLog information.

CY> Please add a NEWS entry as well.

Would this be sufficient?

Ted

Index: NEWS
===================================================================
RCS file: /sources/emacs/emacs/etc/NEWS,v
retrieving revision 1.2042
diff -c -r1.2042 NEWS
*** NEWS	16 Jul 2009 21:04:18 -0000	1.2042
--- NEWS	5 Aug 2009 16:47:25 -0000
***************
*** 24,29 ****
--- 24,37 ----
  \f
  * Changes in Emacs 23.2
  
+ ** Hashtables can be printed and read back directly.  The feature
+ 'hashtable-print-readable identifies this new functionality.
+ Hashtables are printed as alists, but with some hashtable-specific
+ properties and the actual data as an alist in a data property.  Be
+ aware the test property could have a bogus value when it is read back,
+ if the symbol it refers to doesn't exist.
+ 
+ +++
  ** The default value of `trash-directory' has changed to nil, which
  means that `move-file-to-trash' trashes files according to
  freedesktop.org specifications, the same method used by the Gnome,





^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2009-08-05  9:20                                                                                       ` Ted Zlatanov
  2009-08-05 13:48                                                                                         ` Chong Yidong
@ 2009-08-06 10:13                                                                                         ` Dan Nicolaescu
  2009-08-06 16:58                                                                                         ` Florian Beck
  2 siblings, 0 replies; 86+ messages in thread
From: Dan Nicolaescu @ 2009-08-06 10:13 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

Ted Zlatanov <tzz@lifelogs.com> writes:

  > On Mon, 03 Aug 2009 09:53:38 -0500 Ted Zlatanov <tzz@lifelogs.com> wrote: 
  > 
  > TZ> On Sat, 01 Aug 2009 07:35:44 -0400 Chong Yidong <cyd@stupidchicken.com> wrote: 
  > CY> Ted Zlatanov <tzz@lifelogs.com> writes:
  > >>> If it's all right, can I stick to provide/featurep?  It simplifies the
  > >>> client code, plus there are some performance improvements as you noted.
  > 
  > CY> Yes, please use `provide'.
  > 
  > TZ> In that case the patch is fine as is.  Can you please commit it if it is
  > TZ> all right, or let me know and I'll commit it?
  > 
  > I've committed the patch with the usual ChangeLog information.

This patch breaks the build, temacs crashes on startup.

You cannot call Fprovide in print.c, it's initialized later than that.




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2009-08-05 16:48                                                                                           ` Ted Zlatanov
@ 2009-08-06 16:30                                                                                             ` Stefan Monnier
  2009-08-06 16:47                                                                                               ` Ted Zlatanov
  0 siblings, 1 reply; 86+ messages in thread
From: Stefan Monnier @ 2009-08-06 16:30 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

> + ** Hashtables can be printed and read back directly.  The feature
> + 'hashtable-print-readable identifies this new functionality.

Good.

> + Hashtables are printed as alists, but with some hashtable-specific
> + properties and the actual data as an alist in a data property.  Be
> + aware the test property could have a bogus value when it is read back,
> + if the symbol it refers to doesn't exist.

Superfluous.  Don't forget: the NEWS is already too long usually.
It's just there to advertize (and warn of) new features.  The details
are in the manul and the docstrings.


        Stefan




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2009-08-06 16:30                                                                                             ` Stefan Monnier
@ 2009-08-06 16:47                                                                                               ` Ted Zlatanov
  2009-08-08 18:36                                                                                                 ` Chong Yidong
  0 siblings, 1 reply; 86+ messages in thread
From: Ted Zlatanov @ 2009-08-06 16:47 UTC (permalink / raw)
  To: emacs-devel

On Thu, 06 Aug 2009 12:30:10 -0400 Stefan Monnier <monnier@iro.umontreal.ca> wrote: 

>> + ** Hashtables can be printed and read back directly.  The feature
>> + 'hashtable-print-readable identifies this new functionality.

SM> Good.

>> + Hashtables are printed as alists, but with some hashtable-specific
>> + properties and the actual data as an alist in a data property.  Be
>> + aware the test property could have a bogus value when it is read back,
>> + if the symbol it refers to doesn't exist.

SM> Superfluous.  Don't forget: the NEWS is already too long usually.
SM> It's just there to advertize (and warn of) new features.  The details
SM> are in the manul and the docstrings.

OK.  Can you or someone else commit the short version plus the featurep
fix as Andreas suggested earlier?  I won't be able to commit until
tomorrow, unfortunately, and I hate to see the build broken.  Also there
are two new Emacs bugs related to this that can then be closed.

Thanks
Ted





^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2009-08-05  9:20                                                                                       ` Ted Zlatanov
  2009-08-05 13:48                                                                                         ` Chong Yidong
  2009-08-06 10:13                                                                                         ` Dan Nicolaescu
@ 2009-08-06 16:58                                                                                         ` Florian Beck
  2 siblings, 0 replies; 86+ messages in thread
From: Florian Beck @ 2009-08-06 16:58 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

Ted Zlatanov <tzz@lifelogs.com> writes:

> I've committed the patch with the usual ChangeLog information.

I was in eager anticipation for this patch, but I can't get it to work
with strings as keys:

(let ((hashtable (make-hash-table :test 'equal)))
  (puthash "key" "value" hashtable)
  (gethash "key" (car (read-from-string (prin1-to-string hashtable)))))

  => nil

Why?  

-- 
Florian Beck




^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: hash-table-{to, from}-alist
  2009-08-06 16:47                                                                                               ` Ted Zlatanov
@ 2009-08-08 18:36                                                                                                 ` Chong Yidong
  0 siblings, 0 replies; 86+ messages in thread
From: Chong Yidong @ 2009-08-08 18:36 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

Ted Zlatanov <tzz@lifelogs.com> writes:

> SM> Superfluous.  Don't forget: the NEWS is already too long usually.
> SM> It's just there to advertize (and warn of) new features.  The details
> SM> are in the manul and the docstrings.
>
> OK.  Can you or someone else commit the short version plus the featurep
> fix as Andreas suggested earlier?

I've checked in the NEWS entry.




^ permalink raw reply	[flat|nested] 86+ messages in thread

end of thread, other threads:[~2009-08-08 18:36 UTC | newest]

Thread overview: 86+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <34f9604c-a23b-4ad9-9c84-f45884a6df23@x16g2000prn.googlegroups.com>
     [not found] ` <mailman.17732.1219901096.18990.help-gnu-emacs@gnu.org>
     [not found]   ` <bbbc0efc-affc-42dd-bfc0-ebe217ad7073@z6g2000pre.googlegroups.com>
     [not found]     ` <86od3dfd86.fsf@lifelogs.com>
     [not found]       ` <mailman.17796.1219947087.18990.help-gnu-emacs@gnu.org>
     [not found]         ` <868wuflxv9.fsf@lifelogs.com>
     [not found]           ` <mailman.17897.1220021571.18990.help-gnu-emacs@gnu.org>
2008-08-29 18:10             ` print hash table to disk and reread in hash table Ted Zlatanov
2008-08-30  5:18               ` tomas
2008-08-30  9:17                 ` Ted Zlatanov
2008-08-30 12:03                   ` tomas
2008-11-17 17:15                   ` Ted Zlatanov
2008-11-19 21:37                     ` hash-table-{to, from}-alist (was: print hash table to disk and reread in hash table) Ted Zlatanov
2008-11-19 21:57                       ` hash-table-{to, from}-alist Glenn Morris
2008-11-20 19:07                         ` Ted Zlatanov
2008-11-21 22:02                       ` Stefan Monnier
2008-11-21 22:22                         ` Ted Zlatanov
2008-11-22  3:18                           ` Stefan Monnier
2008-11-22  5:45                             ` tomas
2008-11-22 12:27                               ` Stephen J. Turnbull
2008-11-22 15:21                                 ` tomas
2008-11-22 17:38                                   ` Stephen J. Turnbull
2008-11-24 15:44                                     ` Richard M Stallman
2008-11-24 16:58                                       ` Stefan Monnier
2008-11-24 17:21                                       ` Ted Zlatanov
2008-11-25  1:50                                         ` Stephen J. Turnbull
2008-11-25 17:33                                           ` Ted Zlatanov
2008-11-25 23:50                                             ` Ted Zlatanov
2008-11-26  1:46                                               ` Stefan Monnier
2008-11-26  2:16                                                 ` David De La Harpe Golden
2008-11-26  3:48                                                   ` Stefan Monnier
2008-11-26  5:46                                                     ` David De La Harpe Golden
2008-11-26  2:29                                             ` Stephen J. Turnbull
2008-11-26  3:34                                               ` David De La Harpe Golden
2008-11-26 16:06                                               ` Ted Zlatanov
2008-11-26 18:10                                                 ` Stefan Monnier
2008-11-26 20:37                                                   ` Ted Zlatanov
2008-11-26 21:16                                                     ` Ted Zlatanov
2008-12-01 22:01                                                       ` Ted Zlatanov
2008-12-02  0:13                                                         ` Andreas Schwab
2008-12-02 14:27                                                           ` Ted Zlatanov
2008-12-02 21:59                                                           ` Stefan Monnier
2008-12-02 22:20                                                             ` Andreas Schwab
2008-12-02 20:56                                                         ` Ted Zlatanov
2008-12-02 21:27                                                           ` Andreas Schwab
2008-12-02 21:58                                                         ` Stefan Monnier
2008-12-03 19:25                                                           ` Ted Zlatanov
2008-12-04  2:05                                                             ` Stefan Monnier
2008-12-04  6:23                                                               ` Stephen J. Turnbull
2008-12-04  6:34                                                                 ` Miles Bader
2008-12-04  9:08                                                                   ` Andreas Schwab
2008-12-04 13:18                                                                   ` Stefan Monnier
2008-12-04 15:02                                                               ` Ted Zlatanov
2008-12-04 19:34                                                                 ` Stefan Monnier
2008-12-04 19:57                                                                   ` Ted Zlatanov
2009-07-30 18:24                                                                 ` Ted Zlatanov
2009-07-30 19:08                                                                   ` Chong Yidong
2009-07-30 19:22                                                                     ` Ted Zlatanov
2009-07-30 19:40                                                                       ` Chong Yidong
2009-07-30 21:04                                                                         ` Stefan Monnier
2009-07-31  1:30                                                                           ` Stefan Monnier
2009-07-31 17:49                                                                             ` Ted Zlatanov
2009-07-31 19:03                                                                               ` Stefan Monnier
2009-07-31 20:25                                                                                 ` Ted Zlatanov
2009-08-01  2:22                                                                                   ` Stephen J. Turnbull
2009-08-01 11:35                                                                                   ` Chong Yidong
2009-08-03 14:53                                                                                     ` Ted Zlatanov
2009-08-05  9:20                                                                                       ` Ted Zlatanov
2009-08-05 13:48                                                                                         ` Chong Yidong
2009-08-05 16:48                                                                                           ` Ted Zlatanov
2009-08-06 16:30                                                                                             ` Stefan Monnier
2009-08-06 16:47                                                                                               ` Ted Zlatanov
2009-08-08 18:36                                                                                                 ` Chong Yidong
2009-08-06 10:13                                                                                         ` Dan Nicolaescu
2009-08-06 16:58                                                                                         ` Florian Beck
2009-08-03 21:23                                                                                   ` Stefan Monnier
2009-07-31 18:10                                                                           ` Ted Zlatanov
2008-11-27  0:24                                                     ` Stephen J. Turnbull
2008-12-01 21:53                                                       ` Ted Zlatanov
2008-12-02  9:05                                                         ` Stephen J. Turnbull
2008-12-02 14:21                                                           ` Ted Zlatanov
2008-12-02 15:54                                                             ` Stephen J. Turnbull
2008-12-02 16:10                                                               ` Ted Zlatanov
2008-12-02 16:54                                                                 ` Stephen J. Turnbull
2008-12-02 22:19                                                         ` Stefan Monnier
2008-12-02 23:27                                                           ` Ted Zlatanov
2008-11-26 19:44                                                 ` Davis Herring
2008-11-26 20:41                                                   ` Ted Zlatanov
2008-11-25  2:57                                         ` Stefan Monnier
2008-11-25  7:02                                           ` Stephen J. Turnbull
2008-11-22  6:07                             ` Miles Bader
2008-11-22 15:27                               ` tomas
2008-11-22 18:57                             ` Ted Zlatanov

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).