all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* hash strangeness
@ 2014-11-02 11:20 Tom
  2014-11-02 12:09 ` Tom
  0 siblings, 1 reply; 13+ messages in thread
From: Tom @ 2014-11-02 11:20 UTC (permalink / raw)
  To: help-gnu-emacs

Here's a code which gives me some headache. It's silly, because
it was shortened from a longer code to demonstrate the problem.

It is supposed to count something in elisp functions, though
the condition is removed, so with this code the count should be
1 for every function.

So the code checks if the function is already in the hash
and if not then it inserts new info for that function:


(let ((h (make-hash-table :test 'equal)))
  (mapatoms
   (lambda (s)
     (let* ((name (symbol-name s))
            (info (gethash name h)))

       (unless info
         (setq info '(count 0)))

       (setq info (plist-put info
                             'count (1+ (plist-get info 'count))))
                  
       (puthash name info h))))

  (pop-to-buffer "*testout*")
  (erase-buffer)
  (maphash (lambda (name info)
             (insert (format "%s %s" (plist-get info 'count) name) "\n"))
           h))


The new info is newly created in the lambda function (it is
a plist, because in the real code there are other fields too),
yet for some reason the same info structure is used for all
iterations.

I tried to debug it and at the "(unless info" part info is nil
and then it is set to the previous value, though it should be a 
new value.

Am I missing something here?

GNU Emacs 24.1.1 





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

* Re: hash strangeness
  2014-11-02 11:20 Tom
@ 2014-11-02 12:09 ` Tom
  2014-11-02 18:20   ` Thien-Thi Nguyen
  0 siblings, 1 reply; 13+ messages in thread
From: Tom @ 2014-11-02 12:09 UTC (permalink / raw)
  To: help-gnu-emacs

Tom <adatgyujto <at> gmail.com> writes:
> 
>        (unless info
>          (setq info '(count 0)))

It seems it works properly if I use list instead:

        (unless info
          (setq info (list 'count 0)))


Looks like '() is treated like a constant and the same value
is used all the time, though I'm not sure this is what the 
user expects here. 

At least I did not expect that. :)






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

* Re: hash strangeness
  2014-11-02 12:09 ` Tom
@ 2014-11-02 18:20   ` Thien-Thi Nguyen
  2014-11-02 20:45     ` Tom
       [not found]     ` <mailman.12618.1414961152.1147.help-gnu-emacs@gnu.org>
  0 siblings, 2 replies; 13+ messages in thread
From: Thien-Thi Nguyen @ 2014-11-02 18:20 UTC (permalink / raw)
  To: help-gnu-emacs

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

() Tom <adatgyujto@gmail.com>
() Sun, 2 Nov 2014 12:09:31 +0000 (UTC)

   At least I did not expect that. :)

a quote before literal data w/ latent intent to modify?
sez eva: "luate what's created -- i'll tell you no lie!
  but ask me twice
  (or even thrice),
and what was writ is now rot; our shared slate doth cry."

-- 
Thien-Thi Nguyen
   GPG key: 4C807502
   (if you're human and you know it)
      read my lisp: (responsep (questions 'technical)
                               (not (via 'mailing-list)))
                     => nil

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: hash strangeness
       [not found] <mailman.12577.1414927271.1147.help-gnu-emacs@gnu.org>
@ 2014-11-02 18:43 ` Pascal J. Bourguignon
  2014-11-02 20:48   ` Tom
  0 siblings, 1 reply; 13+ messages in thread
From: Pascal J. Bourguignon @ 2014-11-02 18:43 UTC (permalink / raw)
  To: help-gnu-emacs

Tom <adatgyujto@gmail.com> writes:

> Here's a code which gives me some headache. It's silly, because
> it was shortened from a longer code to demonstrate the problem.
>
> It is supposed to count something in elisp functions, though
> the condition is removed, so with this code the count should be
> 1 for every function.
>
> So the code checks if the function is already in the hash
> and if not then it inserts new info for that function:
>
>
> (let ((h (make-hash-table :test 'equal)))
>   (mapatoms
>    (lambda (s)
>      (let* ((name (symbol-name s))
>             (info (gethash name h)))
>
>        (unless info
>          (setq info '(count 0)))
>
>        (setq info (plist-put info
>                              'count (1+ (plist-get info 'count))))
>                   
>        (puthash name info h))))
>
>   (pop-to-buffer "*testout*")
>   (erase-buffer)
>   (maphash (lambda (name info)
>              (insert (format "%s %s" (plist-get info 'count) name) "\n"))
>            h))
>
>
> The new info is newly created in the lambda function (it is
> a plist, because in the real code there are other fields too),
> yet for some reason the same info structure is used for all
> iterations.
>
> I tried to debug it and at the "(unless info" part info is nil
> and then it is set to the previous value, though it should be a 
> new value.
>
> Am I missing something here?

You've identified the problem with the literal list.  However, you could
write it much simplier:

(require 'cl) ; always
(let ((h (make-hash-table :test 'eql))) 
  (mapatoms (lambda (name)
              (incf (getf (gethash name h) 'count 0))))
  (pop-to-buffer "*testout*")
  (erase-buffer)
  (maphash (lambda (name info)
             (insert (format "%s %s\n" (getf info 'count) name)))
           h))

In the current emacs lisp, there's no point in using symbol-name strings
as key in the hash-table: just use symbols with eql as test.
Notice that in emacs lisp:

     (not (equal (symbol-name :hello) (symbol-name 'hello)))


It would be different if emacs lisp had packages like Common Lisp.

-- 
__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


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

* Re: hash strangeness
  2014-11-02 18:20   ` Thien-Thi Nguyen
@ 2014-11-02 20:45     ` Tom
       [not found]     ` <mailman.12618.1414961152.1147.help-gnu-emacs@gnu.org>
  1 sibling, 0 replies; 13+ messages in thread
From: Tom @ 2014-11-02 20:45 UTC (permalink / raw)
  To: help-gnu-emacs

Thien-Thi Nguyen <ttn <at> gnu.org> writes:

> 
> () Tom <adatgyujto <at> gmail.com>
> () Sun, 2 Nov 2014 12:09:31 +0000 (UTC)
> 
>    At least I did not expect that. :)
> 
> a quote before literal data w/ latent intent to modify?

I expect '(a b c) to create a new list with these symbols
every time it runs.

The current behavior (at least in the given context) seems
unuseful, though I'm not a lisp guru, so it's possible
this behavior has its uses in other cases.





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

* Re: hash strangeness
  2014-11-02 18:43 ` hash strangeness Pascal J. Bourguignon
@ 2014-11-02 20:48   ` Tom
  0 siblings, 0 replies; 13+ messages in thread
From: Tom @ 2014-11-02 20:48 UTC (permalink / raw)
  To: help-gnu-emacs

Pascal J. Bourguignon <pjb <at> informatimago.com> writes:
> 
> In the current emacs lisp, there's no point in using symbol-name strings
> as key in the hash-table: just use symbols with eql as test.
> Notice that in emacs lisp:
> 

Of course. The original code transforms the symbol names and 
uses these transformed strings as keys in the hash, so it is
a remnant of simplifying that code into this simple example.




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

* Re: hash strangeness
       [not found]     ` <mailman.12618.1414961152.1147.help-gnu-emacs@gnu.org>
@ 2014-11-02 22:25       ` Pascal J. Bourguignon
  2014-11-02 22:48       ` Barry Margolin
       [not found]       ` <<barmar-14233C.17480902112014@88-209-239-213.giganet.hu>
  2 siblings, 0 replies; 13+ messages in thread
From: Pascal J. Bourguignon @ 2014-11-02 22:25 UTC (permalink / raw)
  To: help-gnu-emacs

Tom <adatgyujto@gmail.com> writes:

> Thien-Thi Nguyen <ttn <at> gnu.org> writes:
>
>> 
>> () Tom <adatgyujto <at> gmail.com>
>> () Sun, 2 Nov 2014 12:09:31 +0000 (UTC)
>> 
>>    At least I did not expect that. :)
>> 
>> a quote before literal data w/ latent intent to modify?
>
> I expect '(a b c) to create a new list with these symbols
> every time it runs.

You expect wrong.


> The current behavior (at least in the given context) seems
> unuseful, though I'm not a lisp guru, so it's possible
> this behavior has its uses in other cases.

Use list, not quote, if you want to create a new list:

    (list 'a 'b 'c)

-- 
__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


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

* Re: hash strangeness
       [not found]     ` <mailman.12618.1414961152.1147.help-gnu-emacs@gnu.org>
  2014-11-02 22:25       ` Pascal J. Bourguignon
@ 2014-11-02 22:48       ` Barry Margolin
  2014-11-03 21:29         ` Tom
       [not found]       ` <<barmar-14233C.17480902112014@88-209-239-213.giganet.hu>
  2 siblings, 1 reply; 13+ messages in thread
From: Barry Margolin @ 2014-11-02 22:48 UTC (permalink / raw)
  To: help-gnu-emacs

In article <mailman.12618.1414961152.1147.help-gnu-emacs@gnu.org>,
 Tom <adatgyujto@gmail.com> wrote:

> Thien-Thi Nguyen <ttn <at> gnu.org> writes:
> 
> > 
> > () Tom <adatgyujto <at> gmail.com>
> > () Sun, 2 Nov 2014 12:09:31 +0000 (UTC)
> > 
> >    At least I did not expect that. :)
> > 
> > a quote before literal data w/ latent intent to modify?
> 
> I expect '(a b c) to create a new list with these symbols
> every time it runs.

Why do you expect that?

'(a b c) is short for (quote (a b c)). quote returns its argument, it 
doesn't make a copy of it.

I'm sure somewhere in the Elisp programming manual it mentions that you 
shouldn't use destructive functions on literal lists, like the Common 
Lisp spec does.

-- 
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***


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

* Re: hash strangeness
  2014-11-02 22:48       ` Barry Margolin
@ 2014-11-03 21:29         ` Tom
  2014-11-04  1:57           ` Robert Thorpe
  2014-11-04  2:16           ` Michael Heerdegen
  0 siblings, 2 replies; 13+ messages in thread
From: Tom @ 2014-11-03 21:29 UTC (permalink / raw)
  To: help-gnu-emacs

Barry Margolin <barmar <at> alum.mit.edu> writes:
> > 
> > I expect '(a b c) to create a new list with these symbols
> > every time it runs.
> 
> Why do you expect that?
> 
> '(a b c) is short for (quote (a b c)). quote returns its argument, it 
> doesn't make a copy of it.

Okay, but when I write '(a b c) in a function then I'd consider it
an ad hoc list in the current context in the function, not as an object
which outlives the exiting of the function and then returns in the
next invocation, unexpectedly connecting the different invocations.


> I'm sure somewhere in the Elisp programming manual it mentions that you 
> shouldn't use destructive functions on literal lists, like the Common 
> Lisp spec does.

Well, the quoting page doesn't mention it:

https://www.gnu.org/software/emacs/manual/html_node/elisp/Quoting.html






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

* Re: hash strangeness
  2014-11-03 21:29         ` Tom
@ 2014-11-04  1:57           ` Robert Thorpe
  2014-11-04  2:16           ` Michael Heerdegen
  1 sibling, 0 replies; 13+ messages in thread
From: Robert Thorpe @ 2014-11-04  1:57 UTC (permalink / raw)
  To: Tom; +Cc: help-gnu-emacs

Tom <adatgyujto@gmail.com> writes:

> Barry Margolin <barmar <at> alum.mit.edu> writes:
>> > 
>> > I expect '(a b c) to create a new list with these symbols
>> > every time it runs.
>> 
>> Why do you expect that?
>> 
>> '(a b c) is short for (quote (a b c)). quote returns its argument, it 
>> doesn't make a copy of it.
>
> Okay, but when I write '(a b c) in a function then I'd consider it
> an ad hoc list in the current context in the function, not as an object
> which outlives the exiting of the function and then returns in the
> next invocation, unexpectedly connecting the different invocations.

Think about C.  Suppose I have:
printf("Hello World!\n");
char *bar = "Goodbye";

In C89 and later both of the strings are constants, they're immutable
data.  If you try to write to one of the characters in "bar" then the
program will crash.  (In earlier versions of C the string would change,
often globally, connecting different invocations of the function.)

Emacs Lisp is similar here.  The list '(a b c) is made by the
interpreter when it's putting the expression into memory.  Quote means
"quote this thing written by the programmer when the program was
written".

>> I'm sure somewhere in the Elisp programming manual it mentions that you 
>> shouldn't use destructive functions on literal lists, like the Common 
>> Lisp spec does.
>
> Well, the quoting page doesn't mention it:
>
> https://www.gnu.org/software/emacs/manual/html_node/elisp/Quoting.html

Yes.  It should probably say "This provides a way to include constant symbols
and constant lists".

I didn't understand this until recently either.

BR,
Robert Thorpe



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

* Re: hash strangeness
  2014-11-03 21:29         ` Tom
  2014-11-04  1:57           ` Robert Thorpe
@ 2014-11-04  2:16           ` Michael Heerdegen
  1 sibling, 0 replies; 13+ messages in thread
From: Michael Heerdegen @ 2014-11-04  2:16 UTC (permalink / raw)
  To: help-gnu-emacs

Tom <adatgyujto@gmail.com> writes:

> Well, the quoting page doesn't mention it:
>
> https://www.gnu.org/software/emacs/manual/html_node/elisp/Quoting.html

I think the doc of `quote' is quite clear in this regard.

This behavior of quote can be confusing when you don't know yet about
it, but once you realize what the lisp reader does, it's normal.


Michael.




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

* RE: hash strangeness
       [not found]       ` <<barmar-14233C.17480902112014@88-209-239-213.giganet.hu>
@ 2014-11-04  3:04         ` Drew Adams
  2014-11-04  7:39           ` Marcin Borkowski
  0 siblings, 1 reply; 13+ messages in thread
From: Drew Adams @ 2014-11-04  3:04 UTC (permalink / raw)
  To: Barry Margolin, help-gnu-emacs

> > I expect '(a b c) to create a new list with these symbols
> > every time it runs.
> 
> Why do you expect that?
> '(a b c) is short for (quote (a b c)). quote returns its argument, it
> doesn't make a copy of it.
> 
> I'm sure somewhere in the Elisp programming manual it mentions that you
> shouldn't use destructive functions on literal lists, like the Common
> Lisp spec does.

Here is one place: the Elisp manual, node `Rearrangement`.  Search for
"a common pitfall".

https://www.gnu.org/software/emacs/manual/html_node/elisp/Rearrangement.html



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

* Re: hash strangeness
  2014-11-04  3:04         ` Drew Adams
@ 2014-11-04  7:39           ` Marcin Borkowski
  0 siblings, 0 replies; 13+ messages in thread
From: Marcin Borkowski @ 2014-11-04  7:39 UTC (permalink / raw)
  To: Barry Margolin, help-gnu-emacs


On 2014-11-04, at 04:04, Drew Adams wrote:

>> > I expect '(a b c) to create a new list with these symbols
>> > every time it runs.
>> 
>> Why do you expect that?
>> '(a b c) is short for (quote (a b c)). quote returns its argument, it
>> doesn't make a copy of it.
>> 
>> I'm sure somewhere in the Elisp programming manual it mentions that you
>> shouldn't use destructive functions on literal lists, like the Common
>> Lisp spec does.
>
> Here is one place: the Elisp manual, node `Rearrangement`.  Search for
> "a common pitfall".
>
> https://www.gnu.org/software/emacs/manual/html_node/elisp/Rearrangement.html

And to see it yourself, execute (e.g. with C-x C-e) the following in
order:

(defun myfun () (setq myvar '(a b c)))
(myfun)
(symbol-value 'myvar)
(symbol-function 'myfun)
(nconc myvar '(1 2 3))
(symbol-value 'myvar)
(symbol-function 'myfun)

Hth,

-- 
Marcin Borkowski
http://octd.wmi.amu.edu.pl/en/Marcin_Borkowski
Adam Mickiewicz University



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

end of thread, other threads:[~2014-11-04  7:39 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <mailman.12577.1414927271.1147.help-gnu-emacs@gnu.org>
2014-11-02 18:43 ` hash strangeness Pascal J. Bourguignon
2014-11-02 20:48   ` Tom
2014-11-02 11:20 Tom
2014-11-02 12:09 ` Tom
2014-11-02 18:20   ` Thien-Thi Nguyen
2014-11-02 20:45     ` Tom
     [not found]     ` <mailman.12618.1414961152.1147.help-gnu-emacs@gnu.org>
2014-11-02 22:25       ` Pascal J. Bourguignon
2014-11-02 22:48       ` Barry Margolin
2014-11-03 21:29         ` Tom
2014-11-04  1:57           ` Robert Thorpe
2014-11-04  2:16           ` Michael Heerdegen
     [not found]       ` <<barmar-14233C.17480902112014@88-209-239-213.giganet.hu>
2014-11-04  3:04         ` Drew Adams
2014-11-04  7:39           ` Marcin Borkowski

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.