GNU bug report logs - #25929
25.2; map-delete doesn't delete permanently 1st alist elt

Previous Next

Package: emacs;

Reported by: Tino Calancha <tino.calancha <at> gmail.com>

Date: Thu, 2 Mar 2017 07:19:01 UTC

Severity: normal

Found in version 25.2

Fixed in version 29.1

Done: Lars Ingebrigtsen <larsi <at> gnus.org>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 25929 in the body.
You can then email your comments to 25929 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to nicolas <at> petton.fr, bug-gnu-emacs <at> gnu.org:
bug#25929; Package emacs. (Thu, 02 Mar 2017 07:19:01 GMT) Full text and rfc822 format available.

Acknowledgement sent to Tino Calancha <tino.calancha <at> gmail.com>:
New bug report received and forwarded. Copy sent to nicolas <at> petton.fr, bug-gnu-emacs <at> gnu.org. (Thu, 02 Mar 2017 07:19:01 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Tino Calancha <tino.calancha <at> gmail.com>
To: bug-gnu-emacs <at> gnu.org
Cc: tino.calancha <at> gmail.com
Subject: 25.2; map-delete doesn't delete permanently 1st alist elt
Date: Thu, 02 Mar 2017 16:17:57 +0900
X-Debbugs-CC: <nicolas <at> petton.fr>

(cl-loop for i below 3 collect
  (let ((map (list (cons 0 3)
                   (cons 1 4)
                   (cons 2 5))))
    (map-delete map i)
    (null (map-elt map i))))
=> (nil t t) ; The first pair, i.e. '(0 . 3) is not permanently deleted.

I've used the word 'permantly' because it seems it is temporary
deleted:

(cl-loop for i below 3 collect
  (let ((map (list (cons 0 3)
                   (cons 1 4)
                   (cons 2 5))))
    (null (map-elt
           (map-delete map i)
           i))))
=> (t t t)

*) It happens just for alist, other maps are fine.
*) The test suite doesn't detect this issue because `test-map-delete'
   happen to delete just the 2rd element of the maps.

In GNU Emacs 25.2.3 (x86_64-pc-linux-gnu, GTK+ Version 3.22.7)
 of 2017-03-02
Repository revision: 640661838dbba8185990e839712c91a14641ddf3




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25929; Package emacs. (Thu, 02 Mar 2017 08:57:01 GMT) Full text and rfc822 format available.

Message #8 received at 25929 <at> debbugs.gnu.org (full text, mbox):

From: Nicolas Petton <nicolas <at> petton.fr>
To: Tino Calancha <tino.calancha <at> gmail.com>, 25929 <at> debbugs.gnu.org
Cc: tino.calancha <at> gmail.com
Subject: Re: bug#25929: 25.2;
 map-delete doesn't delete permanently 1st alist elt
Date: Thu, 02 Mar 2017 09:56:26 +0100
[Message part 1 (text/plain, inline)]
Tino Calancha <tino.calancha <at> gmail.com> writes:

> (cl-loop for i below 3 collect
>   (let ((map (list (cons 0 3)
>                    (cons 1 4)
>                    (cons 2 5))))
>     (map-delete map i)
>     (null (map-elt map i))))
> => (nil t t) ; The first pair, i.e. '(0 . 3) is not permanently
>   deleted.

Thanks for the report! I'll have a look shortly.

Cheers,
Nico
[signature.asc (application/pgp-signature, inline)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25929; Package emacs. (Thu, 02 Mar 2017 11:00:02 GMT) Full text and rfc822 format available.

Message #11 received at 25929 <at> debbugs.gnu.org (full text, mbox):

From: Nicolas Petton <nicolas <at> petton.fr>
To: Tino Calancha <tino.calancha <at> gmail.com>, 25929 <at> debbugs.gnu.org
Cc: Stefan Monnier <monnier <at> iro.umontreal.ca>, tino.calancha <at> gmail.com
Subject: Re: bug#25929: 25.2;
 map-delete doesn't delete permanently 1st alist elt
Date: Thu, 02 Mar 2017 11:59:08 +0100
[Message part 1 (text/plain, inline)]
Tino Calancha <tino.calancha <at> gmail.com> writes:


> (cl-loop for i below 3 collect
>   (let ((map (list (cons 0 3)
>                    (cons 1 4)
>                    (cons 2 5))))
>     (map-delete map i)
>     (null (map-elt map i))))
> => (nil t t) ; The first pair, i.e. '(0 . 3) is not permanently deleted.
>
> I've used the word 'permantly' because it seems it is temporary
> deleted:
>
> (cl-loop for i below 3 collect
>   (let ((map (list (cons 0 3)
>                    (cons 1 4)
>                    (cons 2 5))))
>     (null (map-elt
>            (map-delete map i)
>            i))))
> => (t t t)

The alist is indeed modified within the `map-delete' function, but in an
unexpected way: if the first key is deleted, the variable `map' is
`setq'ed, which has no effect outside of the function.

One fix would be to make `map-delete' a macro:

(defmacro map-delete (map key)
  "Delete KEY from MAP and return MAP.
No error is signaled if KEY is not a key of MAP.  If MAP is an
array, store nil at the index KEY.

  MAP can be a list, hash-table or array."
    `(macroexp-let2 nil key
       (map--dispatch ,map
         :list (setf (alist-get ,key ,map nil t) nil)
         :hash-table (remhash ,key ,map)
         :array (and (>= ,key 0)
                     (<= ,key (seq-length ,map))
                     (aset ,map ,key nil)))
       ,map))

WDYT?

Cheers,
Nico
[signature.asc (application/pgp-signature, inline)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25929; Package emacs. (Thu, 02 Mar 2017 11:31:02 GMT) Full text and rfc822 format available.

Message #14 received at 25929 <at> debbugs.gnu.org (full text, mbox):

From: Tino Calancha <tino.calancha <at> gmail.com>
To: Nicolas Petton <nicolas <at> petton.fr>
Cc: 25929 <at> debbugs.gnu.org, Stefan Monnier <monnier <at> iro.umontreal.ca>,
 Tino Calancha <tino.calancha <at> gmail.com>
Subject: Re: bug#25929: 25.2; map-delete doesn't delete permanently 1st alist
 elt
Date: Thu, 2 Mar 2017 20:30:35 +0900 (JST)
[Message part 1 (text/plain, inline)]

On Thu, 2 Mar 2017, Nicolas Petton wrote:

> Tino Calancha <tino.calancha <at> gmail.com> writes:
>
>
>> (cl-loop for i below 3 collect
>>   (let ((map (list (cons 0 3)
>>                    (cons 1 4)
>>                    (cons 2 5))))
>>     (map-delete map i)
>>     (null (map-elt map i))))
>> => (nil t t) ; The first pair, i.e. '(0 . 3) is not permanently deleted.
>
> The alist is indeed modified within the `map-delete' function, but in an
> unexpected way: if the first key is deleted, the variable `map' is
> `setq'ed, which has no effect outside of the function.
>
> One fix would be to make `map-delete' a macro:
>
> (defmacro map-delete (map key)
>  "Delete KEY from MAP and return MAP.
> No error is signaled if KEY is not a key of MAP.  If MAP is an
> array, store nil at the index KEY.
>
>  MAP can be a list, hash-table or array."
>    `(macroexp-let2 nil key
>       (map--dispatch ,map
>         :list (setf (alist-get ,key ,map nil t) nil)
>         :hash-table (remhash ,key ,map)
>         :array (and (>= ,key 0)
>                     (<= ,key (seq-length ,map))
>                     (aset ,map ,key nil)))
>       ,map))
>

After this patch if i run the above recipe i get an error:
let*: Symbol’s function definition is void: map--dispatch


Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25929; Package emacs. (Thu, 02 Mar 2017 12:28:02 GMT) Full text and rfc822 format available.

Message #17 received at 25929 <at> debbugs.gnu.org (full text, mbox):

From: Nicolas Petton <nicolas <at> petton.fr>
To: Tino Calancha <tino.calancha <at> gmail.com>
Cc: 25929 <at> debbugs.gnu.org, Stefan Monnier <monnier <at> iro.umontreal.ca>,
 Tino Calancha <tino.calancha <at> gmail.com>
Subject: Re: bug#25929: 25.2;
 map-delete doesn't delete permanently 1st alist elt
Date: Thu, 02 Mar 2017 13:27:45 +0100
[Message part 1 (text/plain, inline)]
Tino Calancha <tino.calancha <at> gmail.com> writes:

> After this patch if i run the above recipe i get an error:
> let*: Symbol’s function definition is void: map--dispatch

`map--dispatch' is wrapped into a `eval-when-compile' call.  Evaluate
the macro first?

Cheers,
Nico
[signature.asc (application/pgp-signature, inline)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25929; Package emacs. (Thu, 02 Mar 2017 12:36:02 GMT) Full text and rfc822 format available.

Message #20 received at 25929 <at> debbugs.gnu.org (full text, mbox):

From: Nicolas Petton <nicolas <at> petton.fr>
To: Tino Calancha <tino.calancha <at> gmail.com>, 25929 <at> debbugs.gnu.org
Cc: Stefan Monnier <monnier <at> iro.umontreal.ca>, tino.calancha <at> gmail.com
Subject: Re: bug#25929: 25.2;
 map-delete doesn't delete permanently 1st alist elt
Date: Thu, 02 Mar 2017 13:34:57 +0100
[Message part 1 (text/plain, inline)]
Nicolas Petton <nicolas <at> petton.fr> writes:

> The alist is indeed modified within the `map-delete' function, but in an
> unexpected way: if the first key is deleted, the variable `map' is
> `setq'ed, which has no effect outside of the function.
>
> One fix would be to make `map-delete' a macro:

Here's a fixed version:

  (defmacro map-delete (map key)
    "Delete KEY from MAP and return MAP.
  No error is signaled if KEY is not a key of MAP.  If MAP is an
  array, store nil at the index KEY.
  
  MAP can be a list, hash-table or array."
    (macroexp-let2 nil key
      `(progn
         (map--dispatch ,map
           :list (setf (alist-get ,key ,map nil t) nil)
           :hash-table (remhash ,key ,map)
           :array (and (>= ,key 0)
                       (<= ,key (seq-length ,map))
                       (aset ,map ,key nil)))
         ,map)))

And the associated regression test:

  (ert-deftest test-map-delete-first-key-alist ()
    (let ((alist '((a . 1) (b . 2) (c . 3))))
      (map-delete alist 'a)
      (should (null (map-elt alist 'a)))))

Cheers,
Nico
[signature.asc (application/pgp-signature, inline)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25929; Package emacs. (Thu, 02 Mar 2017 12:36:02 GMT) Full text and rfc822 format available.

Message #23 received at 25929 <at> debbugs.gnu.org (full text, mbox):

From: npostavs <at> users.sourceforge.net
To: Nicolas Petton <nicolas <at> petton.fr>
Cc: 25929 <at> debbugs.gnu.org, Stefan Monnier <monnier <at> iro.umontreal.ca>,
 Tino Calancha <tino.calancha <at> gmail.com>
Subject: Re: bug#25929: 25.2;
 map-delete doesn't delete permanently 1st alist elt
Date: Thu, 02 Mar 2017 07:36:42 -0500
Nicolas Petton <nicolas <at> petton.fr> writes:

>     `(macroexp-let2 nil key

I guess the backquote is in the wrong place?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25929; Package emacs. (Thu, 02 Mar 2017 12:47:01 GMT) Full text and rfc822 format available.

Message #26 received at 25929 <at> debbugs.gnu.org (full text, mbox):

From: Nicolas Petton <nicolas <at> petton.fr>
To: npostavs <at> users.sourceforge.net
Cc: 25929 <at> debbugs.gnu.org, Stefan Monnier <monnier <at> iro.umontreal.ca>,
 Tino Calancha <tino.calancha <at> gmail.com>
Subject: Re: bug#25929: 25.2;
 map-delete doesn't delete permanently 1st alist elt
Date: Thu, 02 Mar 2017 13:45:57 +0100
[Message part 1 (text/plain, inline)]
npostavs <at> users.sourceforge.net writes:

> I guess the backquote is in the wrong place?

Yes, I posted a fix :)
[signature.asc (application/pgp-signature, inline)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25929; Package emacs. (Thu, 02 Mar 2017 13:35:02 GMT) Full text and rfc822 format available.

Message #29 received at 25929 <at> debbugs.gnu.org (full text, mbox):

From: Tino Calancha <tino.calancha <at> gmail.com>
To: Nicolas Petton <nicolas <at> petton.fr>
Cc: 25929 <at> debbugs.gnu.org, Stefan Monnier <monnier <at> iro.umontreal.ca>,
 Tino Calancha <tino.calancha <at> gmail.com>
Subject: Re: bug#25929: 25.2; map-delete doesn't delete permanently 1st alist
 elt
Date: Thu, 2 Mar 2017 22:34:29 +0900 (JST)

On Thu, 2 Mar 2017, Nicolas Petton wrote:

> Nicolas Petton <nicolas <at> petton.fr> writes:
>
>> The alist is indeed modified within the `map-delete' function, but in an
>> unexpected way: if the first key is deleted, the variable `map' is
>> `setq'ed, which has no effect outside of the function.
>>
>> One fix would be to make `map-delete' a macro:
>
> Here's a fixed version:
>
>  (defmacro map-delete (map key)
>    "Delete KEY from MAP and return MAP.
>  No error is signaled if KEY is not a key of MAP.  If MAP is an
>  array, store nil at the index KEY.
>
>  MAP can be a list, hash-table or array."
>    (macroexp-let2 nil key
>      `(progn
>         (map--dispatch ,map
>           :list (setf (alist-get ,key ,map nil t) nil)
>           :hash-table (remhash ,key ,map)
>           :array (and (>= ,key 0)
>                       (<= ,key (seq-length ,map))
>                       (aset ,map ,key nil)))
>         ,map)))
>
> And the associated regression test:
>
>  (ert-deftest test-map-delete-first-key-alist ()
>    (let ((alist '((a . 1) (b . 2) (c . 3))))
>      (map-delete alist 'a)
>      (should (null (map-elt alist 'a)))))

Sorry, i don't understand why following doesn't work after the patch:
;; I have byte-compiled map.el after applying the patch.
emacs -Q

(let ((alist '((a . 1) (b . 2) (c . 3))))
  (map-delete alist 'a)
  (map-elt alist 'a))

Debugger entered--Lisp error: (void-function map--dispatch)

We shouldn't ask the user to compile the file on each interactive session
in order to `map--dispatch' be defined.

We might also mention in the doc strings that MAP must be a generalized
variable or something.
To explain that I) below is allowed but II) is not:
I)
 (assq-delete-all 'foo '((foo . 1) (bar . 2)))

II)
 (map-delete '((foo . 1) (bar . 2)) 'foo)


Regards,
Tino




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25929; Package emacs. (Thu, 02 Mar 2017 15:13:02 GMT) Full text and rfc822 format available.

Message #32 received at 25929 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Nicolas Petton <nicolas <at> petton.fr>
Cc: 25929 <at> debbugs.gnu.org, Tino Calancha <tino.calancha <at> gmail.com>
Subject: Re: bug#25929: 25.2;
 map-delete doesn't delete permanently 1st alist elt
Date: Thu, 02 Mar 2017 10:12:09 -0500
>     (macroexp-let2 nil key
>       `(progn
>          (map--dispatch ,map
>            :list (setf (alist-get ,key ,map nil t) nil)
>            :hash-table (remhash ,key ,map)
>            :array (and (>= ,key 0)
>                        (<= ,key (seq-length ,map))
>                        (aset ,map ,key nil)))
>          ,map)))

Note that this will make it pretty much impossible to use
cl-generic dispatch.

A better option might be to provide a map-remove which works
functionally (i.e. doesn't modify its argument by side-effects), and
then change map-delete to signal an error when we ask to delete the
first element of the list (and to stop returning the "new map" since it
just works imperatively instead).


        Stefan




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25929; Package emacs. (Sat, 04 Mar 2017 00:05:02 GMT) Full text and rfc822 format available.

Message #35 received at 25929 <at> debbugs.gnu.org (full text, mbox):

From: Michael Heerdegen <michael_heerdegen <at> web.de>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: 25929 <at> debbugs.gnu.org, Nicolas Petton <nicolas <at> petton.fr>,
 Tino Calancha <tino.calancha <at> gmail.com>
Subject: Re: bug#25929: 25.2;
 map-delete doesn't delete permanently 1st alist elt
Date: Sat, 04 Mar 2017 01:04:18 +0100
Stefan Monnier <monnier <at> iro.umontreal.ca> writes:

> >     (macroexp-let2 nil key
> >       `(progn
> >          (map--dispatch ,map
> >            :list (setf (alist-get ,key ,map nil t) nil)
> >            :hash-table (remhash ,key ,map)
> >            :array (and (>= ,key 0)
> >                        (<= ,key (seq-length ,map))
> >                        (aset ,map ,key nil)))
> >          ,map)))
>
> Note that this will make it pretty much impossible to use
> cl-generic dispatch.

It will also break cases where MAP is an expression that is not a
symbol:

#+begin_src emacs-lisp
(let ((thing (cons 'tag (list (cons 0 1) (cons 2 3)))))
  (map-delete (cdr thing) 0))
==> nil

(map-delete (list (cons 0 1) (cons 2 3)) 0)
==> if: Symbol's function definition is void: \(setf\ list\)
#+end_src

> A better option might be to provide a map-remove which works
> functionally (i.e. doesn't modify its argument by side-effects), and
> then change map-delete to signal an error when we ask to delete the
> first element of the list (and to stop returning the "new map" since
> it just works imperatively instead).

Why not make it just like `delete': return the map with the entry
removed, the original map might be altered - that's it.

If you want to assign the result back to a symbol/place, use setf or
callf.  Any unnecessary magic just blows up the semantics.

With other words, I would fix this issue by altering the docstring
("return the result" instead of "return MAP") - or am I missing
something?


Michael.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25929; Package emacs. (Sat, 04 Mar 2017 00:18:01 GMT) Full text and rfc822 format available.

Message #38 received at 25929 <at> debbugs.gnu.org (full text, mbox):

From: Michael Heerdegen <michael_heerdegen <at> web.de>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: 25929 <at> debbugs.gnu.org, Nicolas Petton <nicolas <at> petton.fr>,
 Tino Calancha <tino.calancha <at> gmail.com>
Subject: Re: bug#25929: 25.2;
 map-delete doesn't delete permanently 1st alist elt
Date: Sat, 04 Mar 2017 01:16:46 +0100
Michael Heerdegen <michael_heerdegen <at> web.de> writes:

> With other words, I would fix this issue by altering the docstring
> ("return the result" instead of "return MAP")

When the MAP is an alist with only one entry, the return value will be
something different than MAP anyway (a cons cannot be altered to become
nil) - unless we look at "MAP" as a place expression and rewrite the
thing accordingly.  I don't think that is necessary.


Michael.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25929; Package emacs. (Tue, 21 Mar 2017 11:36:02 GMT) Full text and rfc822 format available.

Message #41 received at 25929 <at> debbugs.gnu.org (full text, mbox):

From: Nicolas Petton <nicolas <at> petton.fr>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: 25929 <at> debbugs.gnu.org, Tino Calancha <tino.calancha <at> gmail.com>
Subject: Re: bug#25929: 25.2;
 map-delete doesn't delete permanently 1st alist elt
Date: Tue, 21 Mar 2017 12:35:35 +0100
[Message part 1 (text/plain, inline)]
Stefan Monnier <monnier <at> iro.umontreal.ca> writes:

>>     (macroexp-let2 nil key
>>       `(progn
>>          (map--dispatch ,map
>>            :list (setf (alist-get ,key ,map nil t) nil)
>>            :hash-table (remhash ,key ,map)
>>            :array (and (>= ,key 0)
>>                        (<= ,key (seq-length ,map))
>>                        (aset ,map ,key nil)))
>>          ,map)))
>
> Note that this will make it pretty much impossible to use
> cl-generic dispatch.

Indeed, but I already have that issue.  To use `cl-generic', map.el has
to be basically rewritten from scratch.

> A better option might be to provide a map-remove which works
> functionally (i.e. doesn't modify its argument by side-effects)

I'd love to have that, but what about performance issues with
hash-tables?

hash-tables aren't persistent collections, and having `map-remove',
`map-add', etc. work functionally, the hash-table would have
to be copied for each operation.

Cheers,
Nico
[signature.asc (application/pgp-signature, inline)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25929; Package emacs. (Tue, 21 Mar 2017 15:12:02 GMT) Full text and rfc822 format available.

Message #44 received at 25929 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> IRO.UMontreal.CA>
To: Nicolas Petton <nicolas <at> petton.fr>
Cc: 25929 <at> debbugs.gnu.org, Tino Calancha <tino.calancha <at> gmail.com>
Subject: Re: bug#25929: 25.2;
 map-delete doesn't delete permanently 1st alist elt
Date: Tue, 21 Mar 2017 11:11:20 -0400
>> A better option might be to provide a map-remove which works
>> functionally (i.e. doesn't modify its argument by side-effects)
> I'd love to have that, but what about performance issues with
> hash-tables?

I was thinking of providing map-remove additionally to map-delete (and
make map-delete signal an error when it can't do its job).  IOW declare
that some parts of the API can't be used with all types.


        Stefan




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25929; Package emacs. (Tue, 21 Mar 2017 18:08:02 GMT) Full text and rfc822 format available.

Message #47 received at 25929 <at> debbugs.gnu.org (full text, mbox):

From: Nicolas Petton <nicolas <at> petton.fr>
To: Stefan Monnier <monnier <at> IRO.UMontreal.CA>
Cc: 25929 <at> debbugs.gnu.org, Tino Calancha <tino.calancha <at> gmail.com>
Subject: Re: bug#25929: 25.2;
 map-delete doesn't delete permanently 1st alist elt
Date: Tue, 21 Mar 2017 19:06:56 +0100
[Message part 1 (text/plain, inline)]
Stefan Monnier <monnier <at> IRO.UMontreal.CA> writes:

> I was thinking of providing map-remove additionally to map-delete (and
> make map-delete signal an error when it can't do its job).  IOW declare
> that some parts of the API can't be used with all types.

Yes, that's what I want as well, but then `map-remove' would be
functional (return another map), and it means that it would copy
hash-tables.

Cheers,
Nico
[signature.asc (application/pgp-signature, inline)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25929; Package emacs. (Tue, 21 Mar 2017 20:30:02 GMT) Full text and rfc822 format available.

Message #50 received at 25929 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> IRO.UMontreal.CA>
To: Nicolas Petton <nicolas <at> petton.fr>
Cc: 25929 <at> debbugs.gnu.org, Tino Calancha <tino.calancha <at> gmail.com>
Subject: Re: bug#25929: 25.2;
 map-delete doesn't delete permanently 1st alist elt
Date: Tue, 21 Mar 2017 16:29:46 -0400
>> I was thinking of providing map-remove additionally to map-delete (and
>> make map-delete signal an error when it can't do its job).  IOW declare
>> that some parts of the API can't be used with all types.
> Yes, that's what I want as well, but then `map-remove' would be
> functional (return another map), and it means that it would copy
> hash-tables.

That's right.  Or it could signal an error, if copying is considered to
be "never the right thing to do".


        Stefan




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25929; Package emacs. (Tue, 21 Mar 2017 20:42:02 GMT) Full text and rfc822 format available.

Message #53 received at 25929 <at> debbugs.gnu.org (full text, mbox):

From: Lars Ingebrigtsen <larsi <at> gnus.org>
To: Michael Heerdegen <michael_heerdegen <at> web.de>
Cc: 25929 <at> debbugs.gnu.org, Nicolas Petton <nicolas <at> petton.fr>,
 Stefan Monnier <monnier <at> iro.umontreal.ca>,
 Tino Calancha <tino.calancha <at> gmail.com>
Subject: Re: bug#25929: 25.2;
 map-delete doesn't delete permanently 1st alist elt
Date: Tue, 21 Mar 2017 21:41:01 +0100
Michael Heerdegen <michael_heerdegen <at> web.de> writes:

> Stefan Monnier <monnier <at> iro.umontreal.ca> writes:
>
>> >     (macroexp-let2 nil key
>> >       `(progn
>> >          (map--dispatch ,map
>> >            :list (setf (alist-get ,key ,map nil t) nil)
>> >            :hash-table (remhash ,key ,map)
>> >            :array (and (>= ,key 0)
>> >                        (<= ,key (seq-length ,map))
>> >                        (aset ,map ,key nil)))
>> >          ,map)))
>>
>> Note that this will make it pretty much impossible to use
>> cl-generic dispatch.
>
> It will also break cases where MAP is an expression that is not a
> symbol:
>
> #+begin_src emacs-lisp
> (let ((thing (cons 'tag (list (cons 0 1) (cons 2 3)))))
>   (map-delete (cdr thing) 0))
> ==> nil
>
> (map-delete (list (cons 0 1) (cons 2 3)) 0)
> ==> if: Symbol's function definition is void: \(setf\ list\)
> #+end_src

If MAP isn't a symbol, then map-delete could avoid doing the setf,
couldn't it?

I think that should make for a pretty useful form.  You can both say

...
(map-delete foo 'bar)
...

and

(setq foo (cons (map-delete (get-a-list) 'bar) 'zot))

and not be surprised at the results.  It's certainly more fun than the
current (setq foo (delete 'bar foo)) we have all over the place, even if
it's something of a departure from how functions like this has
traditionally worked in various Lisps.

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25929; Package emacs. (Wed, 22 Mar 2017 11:57:01 GMT) Full text and rfc822 format available.

Message #56 received at 25929 <at> debbugs.gnu.org (full text, mbox):

From: Michael Heerdegen <michael_heerdegen <at> web.de>
To: Lars Ingebrigtsen <larsi <at> gnus.org>
Cc: 25929 <at> debbugs.gnu.org, Nicolas Petton <nicolas <at> petton.fr>,
 Stefan Monnier <monnier <at> iro.umontreal.ca>,
 Tino Calancha <tino.calancha <at> gmail.com>
Subject: Re: bug#25929: 25.2;
 map-delete doesn't delete permanently 1st alist elt
Date: Wed, 22 Mar 2017 12:55:35 +0100
Lars Ingebrigtsen <larsi <at> gnus.org> writes:

> If MAP isn't a symbol, then map-delete could avoid doing the setf,
> couldn't it?
>
> I think that should make for a pretty useful form.  You can both say
>
> ...
> (map-delete foo 'bar)
> ...
>
> and
>
> (setq foo (cons (map-delete (get-a-list) 'bar) 'zot))
>
> and not be surprised at the results.  It's certainly more fun than the
>current (setq foo (delete 'bar foo)) we have all over the place, even
>if it's something of a departure from how functions like this has
>traditionally worked in various Lisps.

So your suggestion is, with other words, that

(1)  (map-delete EXPR 'bar)

is implicitly transformed into

(2)  (cl-callf map-delete EXPR 'bar)

when EXPR is a valid place expression.

That's a relatively small gain, and some people might prefer the
explicit form (2) for readability.

OTOH, without such magic, we can avoid making `map-delete' a macro.
Personally I prefer this simpler approach.


Regards,

Michael.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25929; Package emacs. (Wed, 22 Mar 2017 12:03:01 GMT) Full text and rfc822 format available.

Message #59 received at 25929 <at> debbugs.gnu.org (full text, mbox):

From: Lars Ingebrigtsen <larsi <at> gnus.org>
To: Michael Heerdegen <michael_heerdegen <at> web.de>
Cc: 25929 <at> debbugs.gnu.org, Nicolas Petton <nicolas <at> petton.fr>,
 Stefan Monnier <monnier <at> iro.umontreal.ca>,
 Tino Calancha <tino.calancha <at> gmail.com>
Subject: Re: bug#25929: 25.2;
 map-delete doesn't delete permanently 1st alist elt
Date: Wed, 22 Mar 2017 13:01:46 +0100
Michael Heerdegen <michael_heerdegen <at> web.de> writes:

> That's a relatively small gain, and some people might prefer the
> explicit form (2) for readability.

If we don't do this, (map-delete foo 'bar) has surprising effects in
this one corner case.

That is, if foo is a hash table, then it's fine to say
(map-delete foo 'bar).  If you change foo to be an alist, you then have
to transform all the calls to be (setq foo (map-delete foo 'bar))
instead, which kind of breaks the abstraction that map-delete tried to
offer, I think?

Making map-delete signal an error in the
alist-where-bar-is-the-first-element sounds even worse to me, since the
user may already be writing this stuff as (setq foo (map-delete foo
'bar)).

(I think this was what Stefan suggested...)

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25929; Package emacs. (Wed, 22 Mar 2017 12:57:02 GMT) Full text and rfc822 format available.

Message #62 received at 25929 <at> debbugs.gnu.org (full text, mbox):

From: Noam Postavsky <npostavs <at> users.sourceforge.net>
To: Lars Ingebrigtsen <larsi <at> gnus.org>
Cc: Michael Heerdegen <michael_heerdegen <at> web.de>, 25929 <at> debbugs.gnu.org,
 Nicolas Petton <nicolas <at> petton.fr>, Stefan Monnier <monnier <at> iro.umontreal.ca>,
 Tino Calancha <tino.calancha <at> gmail.com>
Subject: Re: bug#25929: 25.2;
 map-delete doesn't delete permanently 1st alist elt
Date: Wed, 22 Mar 2017 08:56:18 -0400
On Wed, Mar 22, 2017 at 8:01 AM, Lars Ingebrigtsen <larsi <at> gnus.org> wrote:
> Michael Heerdegen <michael_heerdegen <at> web.de> writes:
>
>> That's a relatively small gain, and some people might prefer the
>> explicit form (2) for readability.
>
> If we don't do this, (map-delete foo 'bar) has surprising effects in
> this one corner case.
>
> That is, if foo is a hash table, then it's fine to say
> (map-delete foo 'bar).  If you change foo to be an alist, you then have
> to transform all the calls to be (setq foo (map-delete foo 'bar))
> instead,

It's also fine to say (setq foo (map-delete foo 'bar)) if foo is hash
table, right?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25929; Package emacs. (Wed, 22 Mar 2017 13:32:02 GMT) Full text and rfc822 format available.

Message #65 received at 25929 <at> debbugs.gnu.org (full text, mbox):

From: Lars Ingebrigtsen <larsi <at> gnus.org>
To: Noam Postavsky <npostavs <at> users.sourceforge.net>
Cc: Michael Heerdegen <michael_heerdegen <at> web.de>, 25929 <at> debbugs.gnu.org,
 Nicolas Petton <nicolas <at> petton.fr>, Stefan Monnier <monnier <at> iro.umontreal.ca>,
 Tino Calancha <tino.calancha <at> gmail.com>
Subject: Re: bug#25929: 25.2;
 map-delete doesn't delete permanently 1st alist elt
Date: Wed, 22 Mar 2017 14:31:12 +0100
Noam Postavsky <npostavs <at> users.sourceforge.net> writes:

> It's also fine to say (setq foo (map-delete foo 'bar)) if foo is hash
> table, right?

Sure, but then this isn't a very convenient form to use at all.
Everybody who uses hash tables will use the old form, which makes this
generalisation useless in practice.

I'm not quite sure what the objection to map-delete being a macro is...

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25929; Package emacs. (Wed, 22 Mar 2017 14:44:02 GMT) Full text and rfc822 format available.

Message #68 received at 25929 <at> debbugs.gnu.org (full text, mbox):

From: Michael Heerdegen <michael_heerdegen <at> web.de>
To: Lars Ingebrigtsen <larsi <at> gnus.org>
Cc: 25929 <at> debbugs.gnu.org, Nicolas Petton <nicolas <at> petton.fr>,
 Tino Calancha <tino.calancha <at> gmail.com>,
 Stefan Monnier <monnier <at> iro.umontreal.ca>,
 Noam Postavsky <npostavs <at> users.sourceforge.net>
Subject: Re: bug#25929: 25.2;
 map-delete doesn't delete permanently 1st alist elt
Date: Wed, 22 Mar 2017 15:43:09 +0100
Lars Ingebrigtsen <larsi <at> gnus.org> writes:

> I'm not quite sure what the objection to map-delete being a macro
> is...

It depends on what you find "convenient".  For any macro, I have to
remember which arguments are evaluated and which not, or read the docs
every time I want to use it.  Macros make debugging harder.  Etc.
That's why we usually avoid macros when a function would do.

I understand that you find your suggestion more convenient, but OTOH it
would not be consistent with similar functions we have and introduce
another inconsistency.  I just think it's not worth it.


Michael.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25929; Package emacs. (Wed, 22 Mar 2017 17:03:02 GMT) Full text and rfc822 format available.

Message #71 received at 25929 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> IRO.UMontreal.CA>
To: Lars Ingebrigtsen <larsi <at> gnus.org>
Cc: Michael Heerdegen <michael_heerdegen <at> web.de>, 25929 <at> debbugs.gnu.org,
 Nicolas Petton <nicolas <at> petton.fr>, Tino Calancha <tino.calancha <at> gmail.com>
Subject: Re: bug#25929: 25.2;
 map-delete doesn't delete permanently 1st alist elt
Date: Wed, 22 Mar 2017 13:02:39 -0400
> Making map-delete signal an error in the
> alist-where-bar-is-the-first-element sounds even worse to me, since the
> user may already be writing this stuff as (setq foo (map-delete foo
> 'bar)).
> (I think this was what Stefan suggested...)

Good catch, no, what I'm suggesting is to signal an error when
map-delete is called on an alist (forcing the user to use map-remove
for that instead).


        Stefan




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25929; Package emacs. (Wed, 22 Mar 2017 17:05:01 GMT) Full text and rfc822 format available.

Message #74 received at 25929 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> IRO.UMontreal.CA>
To: Lars Ingebrigtsen <larsi <at> gnus.org>
Cc: Michael Heerdegen <michael_heerdegen <at> web.de>, 25929 <at> debbugs.gnu.org,
 Nicolas Petton <nicolas <at> petton.fr>, Tino Calancha <tino.calancha <at> gmail.com>,
 Noam Postavsky <npostavs <at> users.sourceforge.net>
Subject: Re: bug#25929: 25.2;
 map-delete doesn't delete permanently 1st alist elt
Date: Wed, 22 Mar 2017 13:04:32 -0400
> I'm not quite sure what the objection to map-delete being a macro is...

The problem is how to make it extensible to user-defined types
via something like cl-generic.el (e.g. add support for avl-tree.el
without having to make map.el aware of avl-tree.el).


        Stefan




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25929; Package emacs. (Wed, 22 Mar 2017 17:24:02 GMT) Full text and rfc822 format available.

Message #77 received at 25929 <at> debbugs.gnu.org (full text, mbox):

From: Lars Ingebrigtsen <larsi <at> gnus.org>
To: Stefan Monnier <monnier <at> IRO.UMontreal.CA>
Cc: Michael Heerdegen <michael_heerdegen <at> web.de>, 25929 <at> debbugs.gnu.org,
 Nicolas Petton <nicolas <at> petton.fr>, Tino Calancha <tino.calancha <at> gmail.com>,
 Noam Postavsky <npostavs <at> users.sourceforge.net>
Subject: Re: bug#25929: 25.2;
 map-delete doesn't delete permanently 1st alist elt
Date: Wed, 22 Mar 2017 18:23:03 +0100
Stefan Monnier <monnier <at> IRO.UMontreal.CA> writes:

> The problem is how to make it extensible to user-defined types
> via something like cl-generic.el (e.g. add support for avl-tree.el
> without having to make map.el aware of avl-tree.el).

Hm...  I haven't used cl-generic.el, but having map-delete be something
like this work?

(defmacro map-delete (map elem)
  (if (symbolp map)
      `(setq ,map (map-delete-1 ,map ,elem))
    `(map-delete-1 ,map ,elem)))

And then having map-delete-1 be the thing to support user-defined types?

It'd be kinda an even more unusual Lisp construct, but, on the other
hand, I don't think Lisp has ever come up with an elegant way to express
these mutating functions before, so we're free to innovate.  :-)

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25929; Package emacs. (Wed, 22 Mar 2017 20:32:02 GMT) Full text and rfc822 format available.

Message #80 received at 25929 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> IRO.UMontreal.CA>
To: Lars Ingebrigtsen <larsi <at> gnus.org>
Cc: Michael Heerdegen <michael_heerdegen <at> web.de>, 25929 <at> debbugs.gnu.org,
 Nicolas Petton <nicolas <at> petton.fr>, Tino Calancha <tino.calancha <at> gmail.com>,
 Noam Postavsky <npostavs <at> users.sourceforge.net>
Subject: Re: bug#25929: 25.2;
 map-delete doesn't delete permanently 1st alist elt
Date: Wed, 22 Mar 2017 16:31:26 -0400
>> The problem is how to make it extensible to user-defined types
>> via something like cl-generic.el (e.g. add support for avl-tree.el
>> without having to make map.el aware of avl-tree.el).

> Hm...  I haven't used cl-generic.el, but having map-delete be something
> like this work?

> (defmacro map-delete (map elem)
>   (if (symbolp map)
>       `(setq ,map (map-delete-1 ,map ,elem))
>     `(map-delete-1 ,map ,elem)))

It would work, yes.  I think the resulting semantics is pretty ugly, but
it's just a question of taste.


        Stefan




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25929; Package emacs. (Wed, 29 Mar 2017 15:26:02 GMT) Full text and rfc822 format available.

Message #83 received at 25929 <at> debbugs.gnu.org (full text, mbox):

From: Lars Ingebrigtsen <larsi <at> gnus.org>
To: Michael Heerdegen <michael_heerdegen <at> web.de>
Cc: 25929 <at> debbugs.gnu.org, Nicolas Petton <nicolas <at> petton.fr>,
 Stefan Monnier <monnier <at> iro.umontreal.ca>,
 Tino Calancha <tino.calancha <at> gmail.com>
Subject: Re: bug#25929: 25.2; plists and map-*
Date: Wed, 29 Mar 2017 17:25:46 +0200
A thing just occurred to me: Does the map-* functions work for plists,
too?  plists are, like, the fourth major mapping structure we have in
Lisp.

Wouldn't it be easy to extend map-* to handle plists, too?  For
instance, map-delete (of course) knows whether it's looking at a hash
table or an array, but it can also easily distinguish between an alist
and a plist by just looking at the first element, can't it?

It's a bit hacky, though.  But might be nice.

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25929; Package emacs. (Wed, 29 Mar 2017 15:37:02 GMT) Full text and rfc822 format available.

Message #86 received at 25929 <at> debbugs.gnu.org (full text, mbox):

From: Nicolas Petton <nicolas <at> petton.fr>
To: Lars Ingebrigtsen <larsi <at> gnus.org>,
 Michael Heerdegen <michael_heerdegen <at> web.de>
Cc: 25929 <at> debbugs.gnu.org, Stefan Monnier <monnier <at> iro.umontreal.ca>,
 Tino Calancha <tino.calancha <at> gmail.com>
Subject: Re: bug#25929: 25.2; plists and map-*
Date: Wed, 29 Mar 2017 17:36:41 +0200
[Message part 1 (text/plain, inline)]
Lars Ingebrigtsen <larsi <at> gnus.org> writes:

> A thing just occurred to me: Does the map-* functions work for plists,
> too?  plists are, like, the fourth major mapping structure we have in
> Lisp.

Not currently.

> Wouldn't it be easy to extend map-* to handle plists, too?  For
> instance, map-delete (of course) knows whether it's looking at a hash
> table or an array, but it can also easily distinguish between an alist
> and a plist by just looking at the first element, can't it?

Yes, it would, and was proposed a few weeks ago.

> It's a bit hacky, though.  But might be nice.

It would.  I didn't do it initially exactly because I thought it was a
bit hackish, but I agree that it would be nice to have.

Cheers,
Nico
[signature.asc (application/pgp-signature, inline)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25929; Package emacs. (Wed, 26 Apr 2017 07:59:02 GMT) Full text and rfc822 format available.

Message #89 received at 25929 <at> debbugs.gnu.org (full text, mbox):

From: Nicolas Petton <nicolas <at> petton.fr>
To: Stefan Monnier <monnier <at> IRO.UMontreal.CA>
Cc: 25929 <at> debbugs.gnu.org, Tino Calancha <tino.calancha <at> gmail.com>
Subject: Re: bug#25929: 25.2;
 map-delete doesn't delete permanently 1st alist elt
Date: Wed, 26 Apr 2017 09:58:10 +0200
[Message part 1 (text/plain, inline)]
Stefan Monnier <monnier <at> IRO.UMontreal.CA> writes:

> That's right.  Or it could signal an error, if copying is considered to
> be "never the right thing to do".

If hash-tables were persistent data structures, I'd say that it would
definitely be the right thing to do.

I didn't implement map.el as a functional library because vectors and
hash-tables are not persistent.

Nico
[signature.asc (application/pgp-signature, inline)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25929; Package emacs. (Tue, 26 Apr 2022 13:35:01 GMT) Full text and rfc822 format available.

Message #92 received at 25929 <at> debbugs.gnu.org (full text, mbox):

From: Lars Ingebrigtsen <larsi <at> gnus.org>
To: Tino Calancha <tino.calancha <at> gmail.com>
Cc: 25929 <at> debbugs.gnu.org, nicolas <at> petton.fr
Subject: Re: bug#25929: 25.2; map-delete doesn't delete permanently 1st
 alist elt
Date: Tue, 26 Apr 2022 15:34:00 +0200
Tino Calancha <tino.calancha <at> gmail.com> writes:

> *) It happens just for alist, other maps are fine.

(I'm going through old bug reports that unfortunately weren't resolved
at the time.)

Various things were proposed here, but they all had problems.  So I
don't think there's much to be done here except documenting this, which
I've now done in Emacs 29.

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no




bug marked as fixed in version 29.1, send any further explanations to 25929 <at> debbugs.gnu.org and Tino Calancha <tino.calancha <at> gmail.com> Request was from Lars Ingebrigtsen <larsi <at> gnus.org> to control <at> debbugs.gnu.org. (Tue, 26 Apr 2022 13:35:02 GMT) Full text and rfc822 format available.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25929; Package emacs. (Thu, 28 Apr 2022 03:18:02 GMT) Full text and rfc822 format available.

Message #97 received at 25929 <at> debbugs.gnu.org (full text, mbox):

From: Richard Stallman <rms <at> gnu.org>
To: Lars Ingebrigtsen <larsi <at> gnus.org>
Cc: 25929 <at> debbugs.gnu.org, nicolas <at> petton.fr, tino.calancha <at> gmail.com
Subject: Re: bug#25929: 25.2;
 map-delete doesn't delete permanently 1st alist elt
Date: Wed, 27 Apr 2022 23:17:20 -0400
[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > > *) It happens just for alist, other maps are fine.

  > (I'm going through old bug reports that unfortunately weren't resolved
  > at the time.)

  > Various things were proposed here, but they all had problems.  So I
  > don't think there's much to be done here except documenting this, which
  > I've now done in Emacs 29.

It is a natural consequence of list structure that deleting the first element
doesn't do it destructively, so you need to do
  (setq foo (delq elt foo))

This is a general principal of deletion in Lisp, so let's teach it to
people rather than trying to help people avoid the need to learn it.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)






Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#25929; Package emacs. (Thu, 28 Apr 2022 16:01:02 GMT) Full text and rfc822 format available.

Message #100 received at 25929 <at> debbugs.gnu.org (full text, mbox):

From: Drew Adams <drew.adams <at> oracle.com>
To: "rms <at> gnu.org" <rms <at> gnu.org>, Lars Ingebrigtsen <larsi <at> gnus.org>
Cc: "25929 <at> debbugs.gnu.org" <25929 <at> debbugs.gnu.org>,
 "nicolas <at> petton.fr" <nicolas <at> petton.fr>,
 "tino.calancha <at> gmail.com" <tino.calancha <at> gmail.com>
Subject: RE: [External] : bug#25929: 25.2; map-delete doesn't delete
 permanently 1st alist elt
Date: Thu, 28 Apr 2022 16:00:23 +0000
> It is a natural consequence of list structure that 
> deleting the first element doesn't do it destructively,
> so you need to do (setq foo (delq elt foo))
> 
> This is a general principal of deletion in Lisp, so
> let's teach it to people rather than trying to help
> people avoid the need to learn it.

+1.

bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Fri, 27 May 2022 11:24:04 GMT) Full text and rfc822 format available.

This bug report was last modified 1 year and 328 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.