all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: "Pascal J. Bourguignon" <pjb@informatimago.com>
To: help-gnu-emacs@gnu.org
Subject: Re: plists, alists, and hashtables
Date: Fri, 07 Aug 2015 02:08:58 +0200	[thread overview]
Message-ID: <87h9ocm02t.fsf@kuiper.lan.informatimago.com> (raw)
In-Reply-To: 877fp8t9ru.fsf@lifelogs.com

Ted Zlatanov <tzz@lifelogs.com> writes:

> So you have to do
>
> (delq nil (mapcar #'car-safe '((a) (b 1) (c . 2) d)))
>
> When the backend implementation is also the frontend, as with alists,
> you have to go through the whole alist to collect the keys. That's the
> access-time looping and parsing I mean. By contrast, the hashtable
> implementation (whether it does it now or not) can keep the list of keys
> and update it only when the data is modified.  At access time, the keys
> are instantly available.

Only they are NOT instantly available.  First it has to compute the hash
value, then it has to compute a division to find the modulo, and finally
it still has to walk a list or an array when there are collisions.

All this takes time, so much time that it's faster to walk 100 cons
cells and perform 50 comparisons of the keys in an a-list, that doing
all that in a hash-table!  Benchmarks prove it!

Now, I should mention that emacs lisp is an implementation where the
difference is the biggest.

In clisp (similar to emacs lisp, compiles to a bytecode VM), the
break-even point is at 35 entries, and in other CL implementations
compiling to native code, the break-even point is at 5 or 6 entries.

That means that there's room to optimize hash-tables in emacs lisp.

Nonetheless, there's an incompressible minimum break-even of half a
dozen, and most dictionaries ARE that small.
 


> Maybe the macro is good enough, but I think the keys and values have to
> be clearly separated from each other and from other cells to make it
> visually useful.  

I understand that, and I cannot advise more strongly that you add
newlines and indent your data to clearly show it.

         (hash-table  k1      v1
                      kkkk2   v2
                      k3      vvvvvv3)

(use M-x align-cols)

Notice that often keys are keywords:

         (hash-table  :k1      v1
                      :kkkk2   v2
                      :k3      vvvvvv3)

and emacs fontifies them nicely.


Also, I would admit that using parentheses around the entries could help
editing the data structure, since that allows adding or removing entries
easily with a structural editor like emacs+paredit.

        (mhash-table  (k1      v1)
                      (kkkk2   v2)
                      (k3      vvvvvv3))

It works well enough for a macro (eg. let), but for a function it is a
real bother:

        (fhash-table  '(k1      v1)
                      (list 'kkkk2  (+ 3 4))
                      (list 'k3     (f 'k3)))

Therefore I wouldn't advise to use anything more complex than a even
number of arguments,  alternating keys and values, to a function
constructor.



> The key for me is that I'm not looking to make
> hashtables themselves more prominent, but to give ELisp users a way to
> read and write maps more clearly and in a way that maps more closely to
> a true map data type (which I thought the hashtable was).
>
> The second part of my question was whether Customize support for
> hashtables would make them more approachable and useful.

This could definitely help.


> SM> More importantly, mathematical maps are persistent, whereas your
> SM> apparently favorite implementation (the hash-table) is not persistent,
> SM> contrary to (e.g.) alists.
>
> I am not sure what you mean.  Perhaps it's a problem with the
> terminology.  Could you explain?

SM means immutable.

And indeed, contrarily to the benchmark code I presented earlier, the
natural usage of a-lists is:

Is a key present?    (assoc key alist)            ; O(n)
 
Value for the key:   (cdr (assoc key alist))      ; O(n)

Add a key/value:     (acons key value alist)      ; O(1)

Remove a key:        now, if you use the "Is a key present?" above, 
                     you will need:

                     (remove key alist :key 'car) ; O(n)

                     otherwise (ie. when no value can be nil)
                     you can just do:

                     (acons key nil alist)        ; O(1)

The a-lists are therefore not mutated, and can be shared as the tail of
several variablt a-lists.

(defvar *defaults*   '((:move . walk) (:eat . swallow)))
(defvar *bird*       (acons :move 'fly *defaults*))
(defvar *mouse*      (acons :eat 'chew *defaults*))
(defvar *dead-mouse* (acons :move nil *mouse*))

(list *dead-mouse* *mouse* *bird* *defaults*)
--> (((:move) . #1=((:eat . chew) . #2=((:move . walk) (:eat . swallow))))
     #1# 
     ((:move . fly) . #2#)
     #2#)

-- 
__Pascal Bourguignon__                 http://www.informatimago.com/
“The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.” -- Carl Bass CEO Autodesk


  parent reply	other threads:[~2015-08-07  0:08 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-07-31 21:42 How to iterate over properties in a plist? Marcin Borkowski
2015-07-31 22:18 ` Stefan Monnier
2015-07-31 22:29   ` Marcin Borkowski
2015-07-31 22:42     ` Dmitry Gutov
2015-08-01 13:34       ` Michael Heerdegen
     [not found]   ` <mailman.7705.1438381807.904.help-gnu-emacs@gnu.org>
2015-07-31 23:33     ` Pascal J. Bourguignon
2015-08-01 22:49       ` Stefan Monnier
     [not found]       ` <mailman.7750.1438469396.904.help-gnu-emacs@gnu.org>
2015-08-04 10:15         ` plists, alists, and hashtables (was: How to iterate over properties in a plist?) Ted Zlatanov
2015-08-04 10:29           ` Nicolas Petton
     [not found]           ` <mailman.7809.1438684158.904.help-gnu-emacs@gnu.org>
2015-08-04 11:23             ` plists, alists, and hashtables Ted Zlatanov
2015-08-05  4:36           ` plists, alists, and hashtables (was: How to iterate over properties in a plist?) Rusi
2015-08-05  6:12             ` plists, alists, and hashtables Pascal J. Bourguignon
2015-08-05  9:47               ` Ted Zlatanov
2015-08-05 12:20                 ` Rusi
2015-08-06 19:16                   ` Stefan Monnier
     [not found]                   ` <mailman.7892.1438888819.904.help-gnu-emacs@gnu.org>
2015-08-07 16:33                     ` Rusi
2015-08-05 17:24                 ` Pascal J. Bourguignon
2015-08-05 18:31                   ` Ted Zlatanov
2015-08-05 19:30                     ` Barry Margolin
2015-08-05 19:40                     ` Robert Thorpe
2015-08-05 21:11                     ` Pascal J. Bourguignon
2015-08-06 15:17                       ` Ted Zlatanov
2015-08-06 18:46                         ` Pascal J. Bourguignon
2015-08-06 20:19                           ` Drew Adams
2015-08-06 21:08                           ` Ted Zlatanov
2015-08-07  0:23                             ` Pascal J. Bourguignon
2015-08-06 19:35                         ` Stefan Monnier
2015-08-05 13:48               ` Drew Adams
2015-08-06 19:12           ` Stefan Monnier
     [not found]           ` <mailman.7890.1438888393.904.help-gnu-emacs@gnu.org>
2015-08-06 20:00             ` Pascal J. Bourguignon
2015-08-06 20:57             ` Ted Zlatanov
2015-08-06 21:10               ` Drew Adams
     [not found]               ` <mailman.7902.1438895429.904.help-gnu-emacs@gnu.org>
2015-08-06 21:15                 ` Ted Zlatanov
2015-08-06 21:31               ` Stefan Monnier
2015-08-07  1:53                 ` Ted Zlatanov
2015-08-07  7:34                   ` Pascal J. Bourguignon
2015-08-07 16:32                   ` Stefan Monnier
     [not found]                   ` <mailman.7941.1438965165.904.help-gnu-emacs@gnu.org>
2015-08-08  3:48                     ` Pascal J. Bourguignon
2015-08-08 13:42                       ` Stefan Monnier
2015-08-08 14:51                         ` Rusi
2015-08-07  0:08               ` Pascal J. Bourguignon [this message]
2015-08-07  2:14                 ` Ted Zlatanov
2015-08-07  7:53                   ` Pascal J. Bourguignon
2015-08-07 11:21                     ` Ted Zlatanov
2015-08-07 11:47                       ` Pascal J. Bourguignon
2015-08-07 17:21                         ` Ted Zlatanov
2015-08-07 19:21                           ` Stefan Monnier
     [not found]                           ` <mailman.7952.1438975314.904.help-gnu-emacs@gnu.org>
2015-08-08  3:52                             ` Pascal J. Bourguignon
2015-08-07 16:35                       ` Stefan Monnier
     [not found] <mailman.7856.1438803631.904.help-gnu-emacs@gnu.org>
2015-08-05 20:08 ` Ted Zlatanov
2015-08-05 20:45   ` Stefan Monnier
2015-08-05 21:36   ` Drew Adams
2015-08-05 21:41   ` Pascal J. Bourguignon
     [not found]   ` <mailman.7860.1438807554.904.help-gnu-emacs@gnu.org>
2015-08-06  1:32     ` Ted Zlatanov
     [not found]   ` <mailman.7862.1438810623.904.help-gnu-emacs@gnu.org>
2015-08-06  1:36     ` Ted Zlatanov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87h9ocm02t.fsf@kuiper.lan.informatimago.com \
    --to=pjb@informatimago.com \
    --cc=help-gnu-emacs@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

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

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.