GNU bug report logs -
#75170
add-to-alist: new function
Previous Next
To reply to this bug, email your comments to 75170 AT debbugs.gnu.org.
Toggle the display of automated, internal messages from the tracker.
Report forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Sun, 29 Dec 2024 05:35:02 GMT)
Full text and
rfc822 format available.
Acknowledgement sent
to
Roland Winkler <winkler <at> gnu.org>
:
New bug report received and forwarded. Copy sent to
bug-gnu-emacs <at> gnu.org
.
(Sun, 29 Dec 2024 05:35:03 GMT)
Full text and
rfc822 format available.
Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):
On Mon, 12 Feb 2001, Stephen Gildea wrote:
> Here's a handy function I'd like to see added to Emacs 21: add-to-alist.
> It is like add-to-list, but it looks only at the cars of the element to
> be added and the existing list elements when considering a match. An
> additional optional argument to add-to-alist says what to do if the car
> matches but the cdr does not.
>
> I use this function in my .emacs to update values in alists such as
> default-frame-alist and auto-mode-alist; I'm sure it has other uses.
> My goal in proposing this function is to allow .emacs files to be
> shorter and easier to write. The functions add-to-list and add-hook
> were important steps in that direction; here is another such step.
>
>
> (defun add-to-alist (alist-var elt-cons &optional no-replace)
> "Add to the value of ALIST-VAR an element ELT-CONS if it isn't there yet.
> If an element with the same car as the car of ELT-CONS is already present,
> replace it with ELT-CONS unless NO-REPLACE is non-nil; if a matching
> element is not already present, add ELT-CONS to the front of the alist.
> The test for presence of the car of ELT-CONS is done with `equal'."
> (let ((existing-element (assoc (car elt-cons) (symbol-value alist-var))))
> (if existing-element
> (or no-replace
> (rplacd existing-element (cdr elt-cons)))
> (set alist-var (cons elt-cons (symbol-value alist-var))))))
>
>
> The no-replace argument is useful for setting auto-mode-alist when you
> don't know whether Emacs supports a particular programming language.
> For example, the following suppresses using text-mode for m4 files in
> Emacs 19 but doesn't override using m4-mode in Emacs 20.
>
> (setq default-major-mode 'text-mode)
> (add-to-alist 'auto-mode-alist '("\\.m4\\'" . fundamental-mode) t)
While I thought about a function add-to-alist I found the above thread
from 24 years ago. Stephen's message describes nicely when such a
function can be useful. I suggest to add such a function to subr.el.
The code below follows the conventions of add-to-list.
(defun add-to-alist (alist-var elt-cons &optional no-replace append compare-fn)
"Add ELT-CONS to the value of ALIST-VAR if it isn't there yet.
If an element with the same car as the car of ELT-CONS is already present
in ALIST-VAR, replace it with ELT-CONS unless NO-REPLACE is non-nil.
If a matching element is not yet present, add ELT-CONS at the beginning
of ALIST-VAR. If APPEND is non-nil, add ELT-CONS at the end of ALIST-VAR.
The test for presence of ELT-CONS is done with `equal', or with COMPARE-FN
if that's non-nil.
ALIST-VAR should not refer to a lexical variable.
The return value is the new value of ALIST-VAR."
(let ((elt (cond ((or (null compare-fn) (eq compare-fn #'equal))
(assoc (car elt-cons) (symbol-value alist-var)))
((eq compare-fn #'eq)
(assq (car elt-cons) (symbol-value alist-var)))
(t
(let ((alist (symbol-value alist-var))
(key (car elt-cons)))
(while (and alist
(not (funcall compare-fn key (caar alist))))
(setq alist (cdr alist)))
(car alist))))))
(if elt
(progn
(unless no-replace
(setcdr elt (cdr elt-cons)))
(symbol-value alist-var))
(set alist-var
(if append
(append (symbol-value alist-var) (list elt-cons))
(cons elt-cons (symbol-value alist-var)))))))
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Sun, 29 Dec 2024 06:35:01 GMT)
Full text and
rfc822 format available.
Message #8 received at submit <at> debbugs.gnu.org (full text, mbox):
On Sat, Dec 28 2024, Roland Winkler wrote:
> On Mon, 12 Feb 2001, Stephen Gildea wrote:
>> Here's a handy function I'd like to see added to Emacs 21:
>> add-to-alist.
I forgot to say: I could not find any follow-up or discussion of
Stephen's proposal
https://lists.gnu.org/archive/html/bug-gnu-emacs/2001-02/msg00066.html
I know about the very different approaches underlying the function
add-to-list compared to the macro pushnew. I followed the design of
add-to-list as I am thinking (like Stephen) of similar use cases.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Sun, 29 Dec 2024 07:34:02 GMT)
Full text and
rfc822 format available.
Message #11 received at 75170 <at> debbugs.gnu.org (full text, mbox):
Hello,
Roland Winkler <winkler <at> gnu.org> writes:
> On Mon, 12 Feb 2001, Stephen Gildea wrote:
[...]
> While I thought about a function add-to-alist I found the above thread
> from 24 years ago. Stephen's message describes nicely when such a
> function can be useful. I suggest to add such a function to subr.el.
>
> The code below follows the conventions of add-to-list.
>
> (defun add-to-alist (alist-var elt-cons &optional no-replace append compare-fn)
> "Add ELT-CONS to the value of ALIST-VAR if it isn't there yet.
> If an element with the same car as the car of ELT-CONS is already present
> in ALIST-VAR, replace it with ELT-CONS unless NO-REPLACE is non-nil.
> If a matching element is not yet present, add ELT-CONS at the beginning
> of ALIST-VAR. If APPEND is non-nil, add ELT-CONS at the end of ALIST-VAR.
> The test for presence of ELT-CONS is done with `equal', or with COMPARE-FN
> if that's non-nil.
> ALIST-VAR should not refer to a lexical variable.
>
> The return value is the new value of ALIST-VAR."
> (let ((elt (cond ((or (null compare-fn) (eq compare-fn #'equal))
> (assoc (car elt-cons) (symbol-value alist-var)))
> ((eq compare-fn #'eq)
> (assq (car elt-cons) (symbol-value alist-var)))
> (t
> (let ((alist (symbol-value alist-var))
> (key (car elt-cons)))
> (while (and alist
> (not (funcall compare-fn key (caar alist))))
> (setq alist (cdr alist)))
> (car alist))))))
> (if elt
> (progn
> (unless no-replace
> (setcdr elt (cdr elt-cons)))
> (symbol-value alist-var))
> (set alist-var
> (if append
> (append (symbol-value alist-var) (list elt-cons))
> (cons elt-cons (symbol-value alist-var)))))))
FWIW, in my working branch I use alist-set which does something similar,
I think:
--8<---------------cut here---------------start------------->8---
(defun alist-set (key alist value &optional testfn)
"Associate VALUE with KEY in ALIST, comparing keys with TESTFN."
(setf (alist-get key alist nil nil testfn) value))
--8<---------------cut here---------------end--------------->8---
Cheers,
Eshel
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Sun, 29 Dec 2024 07:51:02 GMT)
Full text and
rfc822 format available.
Message #14 received at 75170 <at> debbugs.gnu.org (full text, mbox):
> From: Roland Winkler <winkler <at> gnu.org>
> Date: Sat, 28 Dec 2024 23:33:56 -0600
>
> On Mon, 12 Feb 2001, Stephen Gildea wrote:
> > Here's a handy function I'd like to see added to Emacs 21: add-to-alist.
> > It is like add-to-list, but it looks only at the cars of the element to
> > be added and the existing list elements when considering a match. An
> > additional optional argument to add-to-alist says what to do if the car
> > matches but the cdr does not.
> >
> > I use this function in my .emacs to update values in alists such as
> > default-frame-alist and auto-mode-alist; I'm sure it has other uses.
> > My goal in proposing this function is to allow .emacs files to be
> > shorter and easier to write. The functions add-to-list and add-hook
> > were important steps in that direction; here is another such step.
> >
> >
> > (defun add-to-alist (alist-var elt-cons &optional no-replace)
> > "Add to the value of ALIST-VAR an element ELT-CONS if it isn't there yet.
> > If an element with the same car as the car of ELT-CONS is already present,
> > replace it with ELT-CONS unless NO-REPLACE is non-nil; if a matching
> > element is not already present, add ELT-CONS to the front of the alist.
> > The test for presence of the car of ELT-CONS is done with `equal'."
> > (let ((existing-element (assoc (car elt-cons) (symbol-value alist-var))))
> > (if existing-element
> > (or no-replace
> > (rplacd existing-element (cdr elt-cons)))
> > (set alist-var (cons elt-cons (symbol-value alist-var))))))
> >
> >
> > The no-replace argument is useful for setting auto-mode-alist when you
> > don't know whether Emacs supports a particular programming language.
> > For example, the following suppresses using text-mode for m4 files in
> > Emacs 19 but doesn't override using m4-mode in Emacs 20.
> >
> > (setq default-major-mode 'text-mode)
> > (add-to-alist 'auto-mode-alist '("\\.m4\\'" . fundamental-mode) t)
>
> While I thought about a function add-to-alist I found the above thread
> from 24 years ago. Stephen's message describes nicely when such a
> function can be useful. I suggest to add such a function to subr.el.
>
> The code below follows the conventions of add-to-list.
>
> (defun add-to-alist (alist-var elt-cons &optional no-replace append compare-fn)
> "Add ELT-CONS to the value of ALIST-VAR if it isn't there yet.
> If an element with the same car as the car of ELT-CONS is already present
> in ALIST-VAR, replace it with ELT-CONS unless NO-REPLACE is non-nil.
> If a matching element is not yet present, add ELT-CONS at the beginning
> of ALIST-VAR. If APPEND is non-nil, add ELT-CONS at the end of ALIST-VAR.
> The test for presence of ELT-CONS is done with `equal', or with COMPARE-FN
> if that's non-nil.
> ALIST-VAR should not refer to a lexical variable.
Thanks.
What is the advantage of adding this function, given that add-to-list
can be used with alists, and given that alist-get can nowadays be used
as a generalize variable?
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Sun, 29 Dec 2024 08:00:02 GMT)
Full text and
rfc822 format available.
Message #17 received at 75170 <at> debbugs.gnu.org (full text, mbox):
>>> Here's a handy function I'd like to see added to Emacs 21:
>>> add-to-alist.
>
> I forgot to say: I could not find any follow-up or discussion of
> Stephen's proposal
>
> https://lists.gnu.org/archive/html/bug-gnu-emacs/2001-02/msg00066.html
>
> I know about the very different approaches underlying the function
> add-to-list compared to the macro pushnew. I followed the design of
> add-to-list as I am thinking (like Stephen) of similar use cases.
While indeed there were no responses to the original message,
other proposed implementations can be found as well, e.g.
https://lists.gnu.org/archive/html/bug-gnu-emacs/2002-04/msg00669.html
https://lists.gnu.org/archive/html/bug-gnu-emacs/2002-04/msg00671.html
Also there are threads discussing 'org--tag-add-to-alist' and
'package--append-to-alist' (renamed from 'package--add-to-alist').
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Sun, 29 Dec 2024 14:51:01 GMT)
Full text and
rfc822 format available.
Message #20 received at 75170 <at> debbugs.gnu.org (full text, mbox):
On Sun, Dec 29 2024, Eli Zaretskii wrote:
> What is the advantage of adding this function, given that add-to-list
> can be used with alists, and given that alist-get can nowadays be used
> as a generalize variable?
The advantage I see for also having the function add-to-alist is the
following:
add-to-list checks for the presence of an element in a list. In the
case of alists, this means it checks for the presence of associations.
You cannot easily modify an existing association with add-to-list. If
you have an alist with association (foo . bar) and you call add-to-list
with an element (foo . baz), add-to-list will not remove the association
(foo . bar), but the alist will then contain both associations.
add-to-alist checks for the presence of keys and it makes sure that each
key appears only once in an alist. By default, it replaces the value of
an existing key. This makes it easy to modify an existing association.
Only with the optional arg NO-REPLACE non-nil, it will preserve an
existing association.
Say, I want in my .emacs file a more complicated association for a key,
and I do not get initially what I want. I can call add-to-alist
multiple times, till I get what I want.
Is there a simple way to accomplish this in other ways (a way that we
recommend for users in their init file if they do not want to use
customize like me)?
Would it make sense to give this functions a different name if more
often it may be used to modify existing associations in an alist instead
of adding new ones?
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Sun, 29 Dec 2024 14:55:02 GMT)
Full text and
rfc822 format available.
Message #23 received at 75170 <at> debbugs.gnu.org (full text, mbox):
On Sun, Dec 29 2024, Juri Linkov wrote:
> Also there are threads discussing 'org--tag-add-to-alist' and
> 'package--append-to-alist' (renamed from 'package--add-to-alist').
My understanding of these functions is that they serve rather different
purposes. They are not intended to be used in user init files.
Severity set to 'wishlist' from 'normal'
Request was from
Stefan Kangas <stefankangas <at> gmail.com>
to
control <at> debbugs.gnu.org
.
(Thu, 02 Jan 2025 01:23:05 GMT)
Full text and
rfc822 format available.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Sun, 05 Jan 2025 15:22:01 GMT)
Full text and
rfc822 format available.
Message #28 received at 75170 <at> debbugs.gnu.org (full text, mbox):
> From: Roland Winkler <winkler <at> gnu.org>
> Cc: 75170 <at> debbugs.gnu.org
> Date: Sun, 29 Dec 2024 08:50:18 -0600
>
> On Sun, Dec 29 2024, Eli Zaretskii wrote:
> > What is the advantage of adding this function, given that add-to-list
> > can be used with alists, and given that alist-get can nowadays be used
> > as a generalize variable?
>
> The advantage I see for also having the function add-to-alist is the
> following:
>
> add-to-list checks for the presence of an element in a list. In the
> case of alists, this means it checks for the presence of associations.
> You cannot easily modify an existing association with add-to-list. If
> you have an alist with association (foo . bar) and you call add-to-list
> with an element (foo . baz), add-to-list will not remove the association
> (foo . bar), but the alist will then contain both associations.
>
> add-to-alist checks for the presence of keys and it makes sure that each
> key appears only once in an alist. By default, it replaces the value of
> an existing key. This makes it easy to modify an existing association.
> Only with the optional arg NO-REPLACE non-nil, it will preserve an
> existing association.
>
> Say, I want in my .emacs file a more complicated association for a key,
> and I do not get initially what I want. I can call add-to-alist
> multiple times, till I get what I want.
>
> Is there a simple way to accomplish this in other ways (a way that we
> recommend for users in their init file if they do not want to use
> customize like me)?
>
> Would it make sense to give this functions a different name if more
> often it may be used to modify existing associations in an alist instead
> of adding new ones?
Let's hear the other co-maintainers.
Stefan and Andrea, WDYT about this? Should we add this function?
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Sat, 18 Jan 2025 09:34:02 GMT)
Full text and
rfc822 format available.
Message #31 received at 75170 <at> debbugs.gnu.org (full text, mbox):
Ping!
> Cc: 75170 <at> debbugs.gnu.org
> Date: Sun, 05 Jan 2025 17:21:00 +0200
> From: Eli Zaretskii <eliz <at> gnu.org>
>
> > From: Roland Winkler <winkler <at> gnu.org>
> > Cc: 75170 <at> debbugs.gnu.org
> > Date: Sun, 29 Dec 2024 08:50:18 -0600
> >
> > On Sun, Dec 29 2024, Eli Zaretskii wrote:
> > > What is the advantage of adding this function, given that add-to-list
> > > can be used with alists, and given that alist-get can nowadays be used
> > > as a generalize variable?
> >
> > The advantage I see for also having the function add-to-alist is the
> > following:
> >
> > add-to-list checks for the presence of an element in a list. In the
> > case of alists, this means it checks for the presence of associations.
> > You cannot easily modify an existing association with add-to-list. If
> > you have an alist with association (foo . bar) and you call add-to-list
> > with an element (foo . baz), add-to-list will not remove the association
> > (foo . bar), but the alist will then contain both associations.
> >
> > add-to-alist checks for the presence of keys and it makes sure that each
> > key appears only once in an alist. By default, it replaces the value of
> > an existing key. This makes it easy to modify an existing association.
> > Only with the optional arg NO-REPLACE non-nil, it will preserve an
> > existing association.
> >
> > Say, I want in my .emacs file a more complicated association for a key,
> > and I do not get initially what I want. I can call add-to-alist
> > multiple times, till I get what I want.
> >
> > Is there a simple way to accomplish this in other ways (a way that we
> > recommend for users in their init file if they do not want to use
> > customize like me)?
> >
> > Would it make sense to give this functions a different name if more
> > often it may be used to modify existing associations in an alist instead
> > of adding new ones?
>
> Let's hear the other co-maintainers.
>
> Stefan and Andrea, WDYT about this? Should we add this function?
>
>
>
>
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Sun, 19 Jan 2025 02:20:02 GMT)
Full text and
rfc822 format available.
Message #34 received at 75170 <at> debbugs.gnu.org (full text, mbox):
Roland Winkler <winkler <at> gnu.org> writes:
> Is there a simple way to accomplish this in other ways (a way that we
> recommend for users in their init file if they do not want to use
> customize like me)?
We indeed recommend using (setf (alist-get ...)), IIUC this is _exactly_
what you were looking for. Your patch contains an implementation of the
setter of `alist-get', and we would add a duplication.
If you did not find this thing, maybe we need to add a hint to some
chapter of the manual?
Michael.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Sun, 19 Jan 2025 06:18:02 GMT)
Full text and
rfc822 format available.
Message #37 received at 75170 <at> debbugs.gnu.org (full text, mbox):
On Sun, Jan 19 2025, Michael Heerdegen wrote:
>> Is there a simple way to accomplish this in other ways (a way that we
>> recommend for users in their init file if they do not want to use
>> customize like me)?
>
> We indeed recommend using (setf (alist-get ...)), IIUC this is _exactly_
> what you were looking for. Your patch contains an implementation of the
> setter of `alist-get', and we would add a duplication.
>
> If you did not find this thing, maybe we need to add a hint to some
> chapter of the manual?
Great! -- It seems, indeed, the code I am looking for does (mostly, see
below) exist. But the "We indeed recommend using..." can be improved.
It should appear at a spot where not only advanced elisp hackers may
have a chance of finding it. But more average users should be able to
find it, too (say, as a strategy for modifying alists in the emacs init
file).
I just noticed: the docstring of alist-get is much more verbose
regarding how this function can be combined with setf than the elisp
manual. So extending the documentation of alist-get in the elisp manual
can already make a big difference! Personally, I always find typical
usage examples in the elisp manual most helpful.
Actually, I just read the docstring from alist-get a couple of times.
And the meaning of the optional arg REMOVE is not clear to me: what is
the "new value" of an association if the key is removed from the alist?
Also, it seems to me there is a difference between add-to-alist and
(setf (alist-get ...)). It was already Stephen Gildea's original
proposal from long time ago to give this function an optional arg
NO-REPLACE, and his proposal included a nice example for when this can
be useful (copied in my first posting). It seems to me that
(setf (alist-get ...)) has no equivalent of NO-REPLACE. Personally,
I have not run in a situation when I had needed this arg; but I can
imagine that it would help others.
Roland
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Sun, 19 Jan 2025 11:24:02 GMT)
Full text and
rfc822 format available.
Message #40 received at 75170 <at> debbugs.gnu.org (full text, mbox):
Eli Zaretskii <eliz <at> gnu.org> writes:
>> From: Roland Winkler <winkler <at> gnu.org>
>> Cc: 75170 <at> debbugs.gnu.org
>> Date: Sun, 29 Dec 2024 08:50:18 -0600
>>
>> On Sun, Dec 29 2024, Eli Zaretskii wrote:
>> > What is the advantage of adding this function, given that add-to-list
>> > can be used with alists, and given that alist-get can nowadays be used
>> > as a generalize variable?
>>
>> The advantage I see for also having the function add-to-alist is the
>> following:
>>
>> add-to-list checks for the presence of an element in a list. In the
>> case of alists, this means it checks for the presence of associations.
>> You cannot easily modify an existing association with add-to-list. If
>> you have an alist with association (foo . bar) and you call add-to-list
>> with an element (foo . baz), add-to-list will not remove the association
>> (foo . bar), but the alist will then contain both associations.
>>
>> add-to-alist checks for the presence of keys and it makes sure that each
>> key appears only once in an alist. By default, it replaces the value of
>> an existing key. This makes it easy to modify an existing association.
>> Only with the optional arg NO-REPLACE non-nil, it will preserve an
>> existing association.
>>
>> Say, I want in my .emacs file a more complicated association for a key,
>> and I do not get initially what I want. I can call add-to-alist
>> multiple times, till I get what I want.
>>
>> Is there a simple way to accomplish this in other ways (a way that we
>> recommend for users in their init file if they do not want to use
>> customize like me)?
>>
>> Would it make sense to give this functions a different name if more
>> often it may be used to modify existing associations in an alist instead
>> of adding new ones?
>
> Let's hear the other co-maintainers.
>
> Stefan and Andrea, WDYT about this? Should we add this function?
The benefit here is that users could more easily replace associations in
alists. Superfluous associations are not the end of the world, as
`alist-get' will anyways only get the first one, but users might not
know that, and it's less aesthetically pleasing.
If Emacs Lisp was just a programming system, then I would be against
this addition as redundant. Since a small subset of ELisp is also used
as a kind of "customization language", I think it occasionally makes
sense to introduce even redundant constructs, provided that it makes
said customization easier. I think this might be one such example.
On balance, I think we could add it.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Sun, 19 Jan 2025 14:35:02 GMT)
Full text and
rfc822 format available.
Message #43 received at 75170 <at> debbugs.gnu.org (full text, mbox):
On Sun, Jan 19 2025, Roland Winkler wrote:
> Actually, I just read the docstring from alist-get a couple of times.
> And the meaning of the optional arg REMOVE is not clear to me: what is
> the "new value" of an association if the key is removed from the alist?
I tried to figure out what the optional arg REMOVE is doing in
alist-get. While I find the code of add-to-alist not too difficult to
grasp at a glance, the optional arg REMOVE is ignored in alist-get. But
it is a more complicated call of gv-define-expander in gv.el that seems
to define REMOVE. For less advanced users, this may be an extra barrier
to put such code into their init file.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Sun, 19 Jan 2025 15:08:02 GMT)
Full text and
rfc822 format available.
Message #46 received at 75170 <at> debbugs.gnu.org (full text, mbox):
Stefan Kangas <stefankangas <at> gmail.com> writes:
> Eli Zaretskii <eliz <at> gnu.org> writes:
>
>>> From: Roland Winkler <winkler <at> gnu.org>
>>> Cc: 75170 <at> debbugs.gnu.org
>>> Date: Sun, 29 Dec 2024 08:50:18 -0600
>>>
>>> On Sun, Dec 29 2024, Eli Zaretskii wrote:
>>> > What is the advantage of adding this function, given that add-to-list
>>> > can be used with alists, and given that alist-get can nowadays be used
>>> > as a generalize variable?
>>>
>>> The advantage I see for also having the function add-to-alist is the
>>> following:
>>>
>>> add-to-list checks for the presence of an element in a list. In the
>>> case of alists, this means it checks for the presence of associations.
>>> You cannot easily modify an existing association with add-to-list. If
>>> you have an alist with association (foo . bar) and you call add-to-list
>>> with an element (foo . baz), add-to-list will not remove the association
>>> (foo . bar), but the alist will then contain both associations.
>>>
>>> add-to-alist checks for the presence of keys and it makes sure that each
>>> key appears only once in an alist. By default, it replaces the value of
>>> an existing key. This makes it easy to modify an existing association.
>>> Only with the optional arg NO-REPLACE non-nil, it will preserve an
>>> existing association.
>>>
>>> Say, I want in my .emacs file a more complicated association for a key,
>>> and I do not get initially what I want. I can call add-to-alist
>>> multiple times, till I get what I want.
>>>
>>> Is there a simple way to accomplish this in other ways (a way that we
>>> recommend for users in their init file if they do not want to use
>>> customize like me)?
>>>
>>> Would it make sense to give this functions a different name if more
>>> often it may be used to modify existing associations in an alist instead
>>> of adding new ones?
>>
>> Let's hear the other co-maintainers.
>>
>> Stefan and Andrea, WDYT about this? Should we add this function?
>
> The benefit here is that users could more easily replace associations in
> alists. Superfluous associations are not the end of the world, as
> `alist-get' will anyways only get the first one, but users might not
> know that, and it's less aesthetically pleasing.
>
> If Emacs Lisp was just a programming system, then I would be against
> this addition as redundant. Since a small subset of ELisp is also used
> as a kind of "customization language", I think it occasionally makes
> sense to introduce even redundant constructs, provided that it makes
> said customization easier. I think this might be one such example.
>
> On balance, I think we could add it.
While you are at it why not implementing a add-to-(a)list function that
add/remove an elemnt at INDEX in list?
It is what I am providing for my users in Helm.
(setq example '((a . 1) (b . 6) (c . 3) (d . 4)))
(helm-add-to-list 'example '(b . 2) 1 'replace)
=>((a . 1) (b . 2) (c . 3) (d . 4))
--
Thierry
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Sun, 19 Jan 2025 19:37:02 GMT)
Full text and
rfc822 format available.
Message #49 received at 75170 <at> debbugs.gnu.org (full text, mbox):
> I just noticed: the docstring of alist-get is much more verbose
> regarding how this function can be combined with setf than the elisp
> manual. So extending the documentation of alist-get in the elisp manual
> can already make a big difference! Personally, I always find typical
> usage examples in the elisp manual most helpful.
One typical usage example:
(setf (alist-get 'sentence (alist-get 'c treesit-thing-settings)) '("statement"))
that replaces the value of the 'c' -> 'sentence' keys in
(setq-local treesit-thing-settings
'((c . ((sexp (not "[](),[{}]"))
(sentence "\\(?:attributed_statement\\)")
(text "\\(?:comment\\|raw_string_literal\\)")))))
> Also, it seems to me there is a difference between add-to-alist and
> (setf (alist-get ...)). It was already Stephen Gildea's original
> proposal from long time ago to give this function an optional arg
> NO-REPLACE, and his proposal included a nice example for when this can
> be useful (copied in my first posting). It seems to me that
> (setf (alist-get ...)) has no equivalent of NO-REPLACE. Personally,
> I have not run in a situation when I had needed this arg; but I can
> imagine that it would help others.
Isn't NO-REPLACE equivalent to this:
(cl-pushnew "statement2" (alist-get 'sentence (alist-get 'c treesit-thing-settings)))
that results in
((c (sexp (not "[](),[{}]"))
(sentence "statement2" "statement")
(text "\\(?:comment\\|raw_string_literal\\)")))
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Sun, 19 Jan 2025 21:19:02 GMT)
Full text and
rfc822 format available.
Message #52 received at 75170 <at> debbugs.gnu.org (full text, mbox):
On Sun, Jan 19 2025, Juri Linkov wrote:
> Isn't NO-REPLACE equivalent to this:
>
> (cl-pushnew "statement2" (alist-get 'sentence (alist-get 'c treesit-thing-settings)))
>
> that results in
>
> ((c (sexp (not "[](),[{}]"))
> (sentence "statement2" "statement")
> (text "\\(?:comment\\|raw_string_literal\\)")))
I am not sure how to read the above example. But it seems to me, it is
different from what NO-REPLACE does. (Anyway, it is a piece of code
that I would not want to suggest to users to put into their init file.)
With NO-REPLACE non-nil, add-to-list will add a new association for KEY,
if KEY is not yet a key in the alist. But if the alist already contains
an association for KEY, this association will not be modified.
Stephen's original proposal illustrated how this can be useful in a
user's init file in the context of auto-mode-alist:
On Mon, 12 Feb 2001, Stephen Gildea wrote:
> The no-replace argument is useful for setting auto-mode-alist when you
> don't know whether Emacs supports a particular programming language.
> For example, the following suppresses using text-mode for m4 files in
> Emacs 19 but doesn't override using m4-mode in Emacs 20.
>
> (setq default-major-mode 'text-mode)
> (add-to-alist 'auto-mode-alist '("\\.m4\\'" . fundamental-mode) t)
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Sun, 19 Jan 2025 21:22:01 GMT)
Full text and
rfc822 format available.
Message #55 received at 75170 <at> debbugs.gnu.org (full text, mbox):
On Sun, Jan 19 2025, Thierry Volpiatto wrote:
> While you are at it why not implementing a add-to-(a)list function that
> add/remove an elemnt at INDEX in list?
> It is what I am providing for my users in Helm.
>
> (setq example '((a . 1) (b . 6) (c . 3) (d . 4)))
>
> (helm-add-to-list 'example '(b . 2) 1 'replace)
>
> =>((a . 1) (b . 2) (c . 3) (d . 4))
I am just curious: when can this be useful? Off my head, I cannot think
of any alists (alists that users my want to modify in their init file)
where order matters.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Mon, 20 Jan 2025 00:29:02 GMT)
Full text and
rfc822 format available.
Message #58 received at 75170 <at> debbugs.gnu.org (full text, mbox):
Stefan Kangas <stefankangas <at> gmail.com> writes:
> On balance, I think we could add it.
But we should definitely have only one implementation in the end.
BTW, this situation is similar to and-let* vs. when-let* where Stefan
wants to remove a similar kind of twin. If a new construct doesn't
provide some kind of advantage we blow up the language and make it more
complex. One has to remember the differences between the twin versions.
So, are we sure that adding something like this is making things easier?
What is the advantage in this case? That it's easier to understand? I
think the examples in the docstring are easy to follow OTOH. If it's
the discoverability, then let's improve that.
And if it's mainly useful for newbies and initialization files, an idea
would be to start a new file init-file-helpers.el or so that aims at
beginners, and add such things to it.
Michael.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Mon, 20 Jan 2025 00:47:01 GMT)
Full text and
rfc822 format available.
Message #61 received at 75170 <at> debbugs.gnu.org (full text, mbox):
Roland Winkler <winkler <at> gnu.org> writes:
> > The no-replace argument is useful for setting auto-mode-alist when you
> > don't know whether Emacs supports a particular programming language.
> > For example, the following suppresses using text-mode for m4 files in
> > Emacs 19 but doesn't override using m4-mode in Emacs 20.
> >
> > (setq default-major-mode 'text-mode)
> > (add-to-alist 'auto-mode-alist '("\\.m4\\'" . fundamental-mode) t)
You can already do something like this, e.g.
(unless (assoc ...) (add-to-list ...))
or
(cl-callf or (alist-get ...) VAL)
Michael.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Mon, 20 Jan 2025 00:53:01 GMT)
Full text and
rfc822 format available.
Message #64 received at 75170 <at> debbugs.gnu.org (full text, mbox):
Stefan Kangas <stefankangas <at> gmail.com> writes:
> On balance, I think we could add it.
Also, we already have a library map.el that is another generalization of
these things. Let's not add a third implementation.
Emacs had once a library alist.el IIRC. Dunno if it had been part of
Emacs or third party, but it had been quite popular. It had been
obsoleted by `alist-get' and map.el. That's not so long ago.
Let's avoid going around in circles and think twice about the final
feature set we aim at, and how we can get there.
Michael.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Mon, 20 Jan 2025 01:06:01 GMT)
Full text and
rfc822 format available.
Message #67 received at 75170 <at> debbugs.gnu.org (full text, mbox):
Roland Winkler <winkler <at> gnu.org> writes:
> Actually, I just read the docstring from alist-get a couple of times.
> And the meaning of the optional arg REMOVE is not clear to me: what is
> the "new value" of an association if the key is removed from the
> alist?
"new value" refers to the second argument of your `setf' call. The
association is removed if you set the associated value to the default
value (nil most of the time) and if REMOVE had been specified.
Michael.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Mon, 20 Jan 2025 03:42:02 GMT)
Full text and
rfc822 format available.
Message #70 received at 75170 <at> debbugs.gnu.org (full text, mbox):
On Mon, Jan 20 2025, Michael Heerdegen wrote:
> Roland Winkler <winkler <at> gnu.org> writes:
>
>> Actually, I just read the docstring from alist-get a couple of times.
>> And the meaning of the optional arg REMOVE is not clear to me: what is
>> the "new value" of an association if the key is removed from the
>> alist?
>
> "new value" refers to the second argument of your `setf' call. The
> association is removed if you set the associated value to the default
> value (nil most of the time) and if REMOVE had been specified.
Why is it not enough to specify the key of the association that is
supposed to be removed from an alist? What is the purpose of making the
removal of an association also dependent on the values of DEFAULT and the
2nd arg for setf?
If there happen to be deep reasons for this, I can't help thinking that
they are not becoming clear from the documentation.
-- I thought about also adding a similar functionality to add-to-alist.
But I could not think of a way that meaningfully aligns with what is
accomplished with the other args of add-to-alist. Removing an
association from an alist is a different story than adding / modifying
an association. For user init files, I would suggest a different
function that will do only that and nothing else, instead of adding more
arguments to add-to-alist.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Mon, 20 Jan 2025 07:26:02 GMT)
Full text and
rfc822 format available.
Message #73 received at 75170 <at> debbugs.gnu.org (full text, mbox):
[Message part 1 (text/plain, inline)]
Roland Winkler <winkler <at> gnu.org> writes:
> On Sun, Jan 19 2025, Thierry Volpiatto wrote:
>> While you are at it why not implementing a add-to-(a)list function that
>> add/remove an elemnt at INDEX in list?
>> It is what I am providing for my users in Helm.
>>
>> (setq example '((a . 1) (b . 6) (c . 3) (d . 4)))
>>
>> (helm-add-to-list 'example '(b . 2) 1 'replace)
>>
>> =>((a . 1) (b . 2) (c . 3) (d . 4))
>
> I am just curious: when can this be useful? Off my head, I cannot think
> of any alists (alists that users my want to modify in their init file)
> where order matters.
Here mainly for helm actions, but I guess there is other use cases.
It is not very hard to implement, so it is a nice extra feature to have IMHO.
--
Thierry
[signature.asc (application/pgp-signature, inline)]
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Mon, 20 Jan 2025 10:00:02 GMT)
Full text and
rfc822 format available.
Message #76 received at 75170 <at> debbugs.gnu.org (full text, mbox):
[Message part 1 (text/plain, inline)]
Roland Winkler <winkler <at> gnu.org> writes:
> On Sun, Jan 19 2025, Thierry Volpiatto wrote:
>> While you are at it why not implementing a add-to-(a)list function that
>> add/remove an elemnt at INDEX in list?
>> It is what I am providing for my users in Helm.
>>
>> (setq example '((a . 1) (b . 6) (c . 3) (d . 4)))
>>
>> (helm-add-to-list 'example '(b . 2) 1 'replace)
>>
>> =>((a . 1) (b . 2) (c . 3) (d . 4))
>
> I am just curious: when can this be useful?
Also the usage of an index allows things like this (what you asked in
first place):
(setq A '((foo . bar) (bar . test) (baz . else)))
(helm-add-to-list 'A '(foo . baz) (cl-position (assoc 'bar A) A) t)
=>((foo . bar) (foo . baz) (baz . else))
--
Thierry
[signature.asc (application/pgp-signature, inline)]
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Mon, 20 Jan 2025 11:28:02 GMT)
Full text and
rfc822 format available.
Message #79 received at 75170 <at> debbugs.gnu.org (full text, mbox):
>>>>> On Sat, 18 Jan 2025 11:33:28 +0200, Eli Zaretskii <eliz <at> gnu.org> said:
Eli> Ping!
>> Cc: 75170 <at> debbugs.gnu.org
>> Date: Sun, 05 Jan 2025 17:21:00 +0200
>> From: Eli Zaretskii <eliz <at> gnu.org>
>>
>> > From: Roland Winkler <winkler <at> gnu.org>
>> > Cc: 75170 <at> debbugs.gnu.org
>> > Date: Sun, 29 Dec 2024 08:50:18 -0600
>> >
>> > On Sun, Dec 29 2024, Eli Zaretskii wrote:
>> > > What is the advantage of adding this function, given that add-to-list
>> > > can be used with alists, and given that alist-get can nowadays be used
>> > > as a generalize variable?
>> >
>> > The advantage I see for also having the function add-to-alist is the
>> > following:
>> >
>> > add-to-list checks for the presence of an element in a list. In the
>> > case of alists, this means it checks for the presence of associations.
>> > You cannot easily modify an existing association with add-to-list. If
>> > you have an alist with association (foo . bar) and you call add-to-list
>> > with an element (foo . baz), add-to-list will not remove the association
>> > (foo . bar), but the alist will then contain both associations.
>> >
>> > add-to-alist checks for the presence of keys and it makes sure that each
>> > key appears only once in an alist. By default, it replaces the value of
>> > an existing key. This makes it easy to modify an existing association.
>> > Only with the optional arg NO-REPLACE non-nil, it will preserve an
>> > existing association.
>> >
>> > Say, I want in my .emacs file a more complicated association for a key,
>> > and I do not get initially what I want. I can call add-to-alist
>> > multiple times, till I get what I want.
>> >
>> > Is there a simple way to accomplish this in other ways (a way that we
>> > recommend for users in their init file if they do not want to use
>> > customize like me)?
>> >
>> > Would it make sense to give this functions a different name if more
>> > often it may be used to modify existing associations in an alist instead
>> > of adding new ones?
>>
>> Let's hear the other co-maintainers.
>>
>> Stefan and Andrea, WDYT about this? Should we add this function?
Iʼm not sure what this would offer over
(setf (alist-get key alist) value)
which will add a key->value mapping if it doesnʼt exist, and replace
it if it does. I also donʼt see a real use for retaining the existing
mapping: `alist-get' will return the first one anyway.
Robert
--
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Mon, 20 Jan 2025 13:42:02 GMT)
Full text and
rfc822 format available.
Message #82 received at 75170 <at> debbugs.gnu.org (full text, mbox):
Roland Winkler <winkler <at> gnu.org> writes:
> Why is it not enough to specify the key of the association that is
> supposed to be removed from an alist? What is the purpose of making the
> removal of an association also dependent on the values of DEFAULT and the
> 2nd arg for setf?
Please do not limit your considerations to this special case. DEFAULT
and the second arg of setf are different things. The expression you
setf to is not necessarily a constant:
(setf (alist-get ...) (get-the-element)).
About your second question: Please also think about the general case.
The promise of (setf PLACE VAL) is that VAL will be stored in PLACE
after the operation. The REMOVE arg just means: it is allowed to
achieve that by removing an association when appropriate.
(alist-get ... DEFAULT ...) will return DEFAULT
when an element is not present. If we setf to a different value we
can't remove anything from the alist because our promise would not hold
and it would not be appropriate.
Michael.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Mon, 20 Jan 2025 19:10:02 GMT)
Full text and
rfc822 format available.
Message #85 received at 75170 <at> debbugs.gnu.org (full text, mbox):
On Mon, Jan 20 2025, Michael Heerdegen wrote:
> Please do not limit your considerations to this special case. DEFAULT
> and the second arg of setf are different things. The expression you
> setf to is not necessarily a constant:
>
> (setf (alist-get ...) (get-the-element)).
>
>
> About your second question: Please also think about the general case.
>
> The promise of (setf PLACE VAL) is that VAL will be stored in PLACE
> after the operation. The REMOVE arg just means: it is allowed to
> achieve that by removing an association when appropriate.
>
> (alist-get ... DEFAULT ...) will return DEFAULT
> when an element is not present. If we setf to a different value we
> can't remove anything from the alist because our promise would not hold
> and it would not be appropriate.
Sure. - I just do not know real-world examples where this combination of
things is an efficient way to go.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Mon, 20 Jan 2025 23:29:02 GMT)
Full text and
rfc822 format available.
Message #88 received at 75170 <at> debbugs.gnu.org (full text, mbox):
Roland Winkler <winkler <at> gnu.org> writes:
> On Mon, Jan 20 2025, Robert Pluim wrote:
>> Iʼm not sure what this would offer over
>>
>> (setf (alist-get key alist) value)
>>
>> which will add a key->value mapping if it doesnʼt exist, and replace
>> it if it does. I also donʼt see a real use for retaining the existing
>> mapping: `alist-get' will return the first one anyway.
>
> By now, this approach has been proposed in this thread a few times.
> The question is: this uses the concept of generalized variables.
> Is this a concept we recommend to users for their init files?
> To the best of my knowledge, previously this has not been the case.
> I am tempted to argue that in our recommendations what users should
> do in their init files, we should stick to strategies that are as
> simple and transparent as possible, and the above does not match
> that criterion. A collection of functions we recommend to users for
> their init files might be a good thing. add-to-list already serves
> that specific purpose, and add-to-alist could be another one.
I certainly appreciate the arguments against adding more redundancy to
ELisp, but I think the point still stands that Emacs should be easy to
customize. Generalized variables don't do that job in my book.
Michael Heerdegen pointed out that `map-put!` could though, given:
(setq foo '((clown . foot) (thunder . clap)))
We get:
(map-put! foo 'clown 'hand)
Which I compare to:
(add-to-alist foo '((clown . hand)))
Is that a workable alternative? We lose the symmetry with `add-to-list`
of course, but there are fewer parentheses and dots to get wrong, and
all we need do is promote it. Which may or may not be easy.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Mon, 20 Jan 2025 23:45:02 GMT)
Full text and
rfc822 format available.
Message #91 received at 75170 <at> debbugs.gnu.org (full text, mbox):
Roland Winkler <winkler <at> gnu.org> writes:
> Sure. - I just do not know real-world examples where this combination of
> things is an efficient way to go.
I don't know what you mean by "efficient", but the Emacs code base has
examples of uses. You might want to have a look at them.
Michael.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Tue, 21 Jan 2025 00:07:02 GMT)
Full text and
rfc822 format available.
Message #94 received at 75170 <at> debbugs.gnu.org (full text, mbox):
On Mon, Jan 20 2025, Stefan Kangas wrote:
> Michael Heerdegen pointed out that `map-put!` could though, given:
>
> (setq foo '((clown . foot) (thunder . clap)))
>
> We get:
>
> (map-put! foo 'clown 'hand)
How does map-put! test for the presence of a key (by default)?
This is not documented in the docstring.
> Which I compare to:
>
> (add-to-alist foo '((clown . hand)))
I think this should read
(add-to-alist 'foo '(clown . hand))
which has fewer parentheses, but foo must be quoted, like with add-to-list.
> Is that a workable alternative? We lose the symmetry with `add-to-list`
> of course, but there are fewer parentheses and dots to get wrong, and
> all we need do is promote it. Which may or may not be easy.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Tue, 21 Jan 2025 00:16:02 GMT)
Full text and
rfc822 format available.
Message #97 received at 75170 <at> debbugs.gnu.org (full text, mbox):
On Mon, Jan 20 2025, Robert Pluim wrote:
> Iʼm not sure what this would offer over
>
> (setf (alist-get key alist) value)
>
> which will add a key->value mapping if it doesnʼt exist, and replace
> it if it does. I also donʼt see a real use for retaining the existing
> mapping: `alist-get' will return the first one anyway.
By now, this approach has been proposed in this thread a few times.
The question is: this uses the concept of generalized variables.
Is this a concept we recommend to users for their init files?
To the best of my knowledge, previously this has not been the case.
I am tempted to argue that in our recommendations what users should
do in their init files, we should stick to strategies that are as
simple and transparent as possible, and the above does not match
that criterion. A collection of functions we recommend to users for
their init files might be a good thing. add-to-list already serves
that specific purpose, and add-to-alist could be another one.
Roland
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Tue, 21 Jan 2025 00:26:01 GMT)
Full text and
rfc822 format available.
Message #100 received at 75170 <at> debbugs.gnu.org (full text, mbox):
Roland Winkler <winkler <at> gnu.org> writes:
> On Mon, Jan 20 2025, Stefan Kangas wrote:
>> Michael Heerdegen pointed out that `map-put!` could though, given:
>>
>> (setq foo '((clown . foot) (thunder . clap)))
>>
>> We get:
>>
>> (map-put! foo 'clown 'hand)
>
> How does map-put! test for the presence of a key (by default)?
> This is not documented in the docstring.
It's not documented, but my testing shows that after the above recipe,
foo has this value:
((clown . hand) (thunder . clap))
>> Which I compare to:
>>
>> (add-to-alist foo '((clown . hand)))
>
> I think this should read
>
> (add-to-alist 'foo '(clown . hand))
>
> which has fewer parentheses, but foo must be quoted, like with add-to-list.
You're right, thanks for correcting that. So less ugly than what I
wrote, and close to what an alist looks like anyways.
I'm curious to hear more opinions about `map-put!`. I'm also copying in
Stefan Monnier, who added that function (or at least named it).
>> Is that a workable alternative? We lose the symmetry with `add-to-list`
>> of course, but there are fewer parentheses and dots to get wrong, and
>> all we need do is promote it. Which may or may not be easy.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Tue, 21 Jan 2025 08:23:02 GMT)
Full text and
rfc822 format available.
Message #103 received at 75170 <at> debbugs.gnu.org (full text, mbox):
>>>>> On Mon, 20 Jan 2025 15:40:48 -0600, Stefan Kangas <stefankangas <at> gmail.com> said:
Stefan> I'm curious to hear more opinions about `map-put!`. I'm also copying in
Stefan> Stefan Monnier, who added that function (or at least named it).
map-put! does not work well with alists that are not 'proper':
ELISP> (setq x (list 1 '(2 . 3)))
(1 (2 . 3))
ELISP> (map-put! x 2 4)
4
(#o4, #x4, ?\C-d)
ELISP> x
(1 (2 . 3) 2 4)
ELISP> (alist-get 2 x)
3
(#o3, #x3, ?\C-c)
ELISP> (setf (alist-get 2 x) 5)
5
(#o5, #x5, ?\C-e)
ELISP> x
(1 (2 . 5) 2 4)
If the intent is to have something thatʼs easy to use and footgun-free
for beginners, then I donʼt think `map-put!' is it.
Robert
--
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Tue, 21 Jan 2025 09:07:02 GMT)
Full text and
rfc822 format available.
Message #106 received at 75170 <at> debbugs.gnu.org (full text, mbox):
Stefan> I'm curious to hear more opinions about `map-put!`. I'm also copying in
Stefan> Stefan Monnier, who added that function (or at least named it).
map-put! does not work well with alists that are not 'proper':
ELISP> (setq x (list 1 '(2 . 3)))
(1 (2 . 3))
Why should it work on alists at all? map-put! assumes a map (where is
this structure documented? I did not see anything in the Elisp
manual), not an alist. Invalid alists will also not work on functions
that assume alists.
(assoc-delete-all 1 '(1 (2 . 3))) does not delete 1.
ELISP> (map-put! x 2 4)
4
(#o4, #x4, ?\C-d)
ELISP> x
(1 (2 . 3) 2 4)
ELISP> (alist-get 2 x)
3
(#o3, #x3, ?\C-c)
ELISP> (setf (alist-get 2 x) 5)
5
(#o5, #x5, ?\C-e)
ELISP> x
(1 (2 . 5) 2 4)
If the intent is to have something thatʼs easy to use and footgun-free
for beginners, then I donʼt think `map-put!' is it.
Robert
--
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Tue, 21 Jan 2025 09:13:01 GMT)
Full text and
rfc822 format available.
Message #109 received at 75170 <at> debbugs.gnu.org (full text, mbox):
"Alfred M. Szmidt" <ams <at> gnu.org> writes:
> map-put! does not work well with alists that are not 'proper':
>
> ELISP> (setq x (list 1 '(2 . 3)))
> (1 (2 . 3))
>
> Why should it work on alists at all? map-put! assumes a map (where is
> this structure documented? I did not see anything in the Elisp
> manual), not an alist. Invalid alists will also not work on functions
> that assume alists.
According to M-x describe-package RET map RET:
map.el provides generic map-manipulation functions that work on
alists, plists, hash-tables, and arrays. All functions are
prefixed with "map-".
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Tue, 21 Jan 2025 09:36:02 GMT)
Full text and
rfc822 format available.
Message #112 received at 75170 <at> debbugs.gnu.org (full text, mbox):
>>>>> On Tue, 21 Jan 2025 03:12:43 -0600, Stefan Kangas <stefankangas <at> gmail.com> said:
Stefan> "Alfred M. Szmidt" <ams <at> gnu.org> writes:
>> map-put! does not work well with alists that are not 'proper':
>>
ELISP> (setq x (list 1 '(2 . 3)))
>> (1 (2 . 3))
>>
>> Why should it work on alists at all? map-put! assumes a map (where is
>> this structure documented? I did not see anything in the Elisp
>> manual), not an alist. Invalid alists will also not work on functions
>> that assume alists.
"invalid alists" is not something that Emacs really cares about:
ELISP> (setq y '(1 (2 . 4) 3))
(1 (2 . 4) 3)
ELISP> (assoc 2 y)
(2 . 4)
ELISP> (setf (alist-get 2 y) 66)
66
(#o102, #x42, ?B)
ELISP> (assoc 2 y)
(2 . 66)
ELISP> y
(1 (2 . 66) 3)
Stefan> According to M-x describe-package RET map RET:
Stefan> map.el provides generic map-manipulation functions that work on
Stefan> alists, plists, hash-tables, and arrays. All functions are
Stefan> prefixed with "map-".
Yes. Except that map.el expects alists to be 'proper'.
Robert
--
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Tue, 21 Jan 2025 10:34:02 GMT)
Full text and
rfc822 format available.
Message #115 received at 75170 <at> debbugs.gnu.org (full text, mbox):
"Alfred M. Szmidt" <ams <at> gnu.org> writes:
> map-put! does not work well with alists that are not 'proper':
>
> ELISP> (setq x (list 1 '(2 . 3)))
> (1 (2 . 3))
>
> Why should it work on alists at all? map-put! assumes a map (where is
> this structure documented? I did not see anything in the Elisp
> manual), not an alist. Invalid alists will also not work on functions
> that assume alists.
According to M-x describe-package RET map RET:
map.el provides generic map-manipulation functions that work on
alists, plists, hash-tables, and arrays. All functions are
prefixed with "map-".
That seems like it cannot possibly work (or very complicated). How do
you differetnate between a plist and alist? Order in an alist is
important, but not in a plist. Their syntax is exactly the same, how
can a insertion function work correctly for that?
The above sounds like it is also overloading the concept of
sequencess?
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Tue, 21 Jan 2025 10:35:02 GMT)
Full text and
rfc822 format available.
Message #118 received at 75170 <at> debbugs.gnu.org (full text, mbox):
>>>>> On Tue, 21 Jan 2025 03:12:43 -0600, Stefan Kangas <stefankangas <at> gmail.com> said:
Stefan> "Alfred M. Szmidt" <ams <at> gnu.org> writes:
>> map-put! does not work well with alists that are not 'proper':
>>
ELISP> (setq x (list 1 '(2 . 3)))
>> (1 (2 . 3))
>>
>> Why should it work on alists at all? map-put! assumes a map (where is
>> this structure documented? I did not see anything in the Elisp
>> manual), not an alist. Invalid alists will also not work on functions
>> that assume alists.
"invalid alists" is not something that Emacs really cares about:
Right, so why should map-foo care about such lists? You're saying it
"expects" them to be alists, but if it gets another list that is not
an alist .. it fails. That is the same behaviour as rest of Emacs,
no?
ELISP> (setq y '(1 (2 . 4) 3))
(1 (2 . 4) 3)
ELISP> (assoc 2 y)
(2 . 4)
ELISP> (setf (alist-get 2 y) 66)
66
(#o102, #x42, ?B)
ELISP> (assoc 2 y)
(2 . 66)
ELISP> y
(1 (2 . 66) 3)
Stefan> According to M-x describe-package RET map RET:
Stefan> map.el provides generic map-manipulation functions that work on
Stefan> alists, plists, hash-tables, and arrays. All functions are
Stefan> prefixed with "map-".
Yes. Except that map.el expects alists to be 'proper'.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Tue, 21 Jan 2025 10:54:01 GMT)
Full text and
rfc822 format available.
Message #121 received at 75170 <at> debbugs.gnu.org (full text, mbox):
>>>>> On Tue, 21 Jan 2025 05:33:50 -0500, "Alfred M. Szmidt" <ams <at> gnu.org> said:
Alfred> Right, so why should map-foo care about such lists? You're saying it
Alfred> "expects" them to be alists, but if it gets another list that is not
Alfred> an alist .. it fails. That is the same behaviour as rest of Emacs,
Alfred> no?
Except that alist-get, assoc, etc donʼt fail (or at least: the
resulting structure is more coherent than what map-put! produces).
Robert
--
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Tue, 21 Jan 2025 10:58:01 GMT)
Full text and
rfc822 format available.
Message #124 received at 75170 <at> debbugs.gnu.org (full text, mbox):
>>>>> On Tue, 21 Jan 2025 05:33:48 -0500, "Alfred M. Szmidt" <ams <at> gnu.org> said:
Alfred> "Alfred M. Szmidt" <ams <at> gnu.org> writes:
>> map-put! does not work well with alists that are not 'proper':
>>
ELISP> (setq x (list 1 '(2 . 3)))
>> (1 (2 . 3))
>>
>> Why should it work on alists at all? map-put! assumes a map (where is
>> this structure documented? I did not see anything in the Elisp
>> manual), not an alist. Invalid alists will also not work on functions
>> that assume alists.
Alfred> According to M-x describe-package RET map RET:
Alfred> map.el provides generic map-manipulation functions that work on
Alfred> alists, plists, hash-tables, and arrays. All functions are
Alfred> prefixed with "map-".
Alfred> That seems like it cannot possibly work (or very complicated). How do
Alfred> you differetnate between a plist and alist? Order in an alist is
Alfred> important, but not in a plist. Their syntax is exactly the same, how
Alfred> can a insertion function work correctly for that?
map.el assumes that a list that starts with an atom is a plist, and
any other list is an alist. alist-get and assoc obviously disagree.
Robert
--
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Tue, 21 Jan 2025 11:36:01 GMT)
Full text and
rfc822 format available.
Message #127 received at 75170 <at> debbugs.gnu.org (full text, mbox):
>>>>> On Tue, 21 Jan 2025 05:33:50 -0500, "Alfred M. Szmidt" <ams <at> gnu.org> said:
Alfred> Right, so why should map-foo care about such lists? You're saying it
Alfred> "expects" them to be alists, but if it gets another list that is not
Alfred> an alist .. it fails. That is the same behaviour as rest of Emacs,
Alfred> no?
Except that alist-get, assoc, etc donʼt fail (or at least: the
resulting structure is more coherent than what map-put! produces).
I don't follow, your example with map-put! did not fail just strange
result, which is no different if you use alist/plist specific
functions on thigns that are not plists or alists.
map-put! cannot know if the thing it is stuff things into is a plist,
alist, list ... which is why this type of function can never really be
well behaved. The alist/plist functions are specially named for that
reason.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Tue, 21 Jan 2025 13:10:01 GMT)
Full text and
rfc822 format available.
Message #130 received at 75170 <at> debbugs.gnu.org (full text, mbox):
>>>>> On Tue, 21 Jan 2025 05:33:48 -0500, "Alfred M. Szmidt" <ams <at> gnu.org> said:
Alfred> "Alfred M. Szmidt" <ams <at> gnu.org> writes:
>> map-put! does not work well with alists that are not 'proper':
>>
ELISP> (setq x (list 1 '(2 . 3)))
>> (1 (2 . 3))
>>
>> Why should it work on alists at all? map-put! assumes a map (where is
>> this structure documented? I did not see anything in the Elisp
>> manual), not an alist. Invalid alists will also not work on functions
>> that assume alists.
Alfred> According to M-x describe-package RET map RET:
Alfred> map.el provides generic map-manipulation functions that work on
Alfred> alists, plists, hash-tables, and arrays. All functions are
Alfred> prefixed with "map-".
Alfred> That seems like it cannot possibly work (or very complicated). How do
Alfred> you differetnate between a plist and alist? Order in an alist is
Alfred> important, but not in a plist. Their syntax is exactly the same, how
Alfred> can a insertion function work correctly for that?
map.el assumes that a list that starts with an atom is a plist, and
any other list is an alist. alist-get and assoc obviously disagree.
That is just wrong.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Tue, 21 Jan 2025 13:10:02 GMT)
Full text and
rfc822 format available.
Message #133 received at 75170 <at> debbugs.gnu.org (full text, mbox):
>>>>> On Tue, 21 Jan 2025 05:33:48 -0500, "Alfred M. Szmidt" <ams <at> gnu.org> said:
Alfred> "Alfred M. Szmidt" <ams <at> gnu.org> writes:
>> map-put! does not work well with alists that are not 'proper':
>>
ELISP> (setq x (list 1 '(2 . 3)))
>> (1 (2 . 3))
>>
>> Why should it work on alists at all? map-put! assumes a map (where is
>> this structure documented? I did not see anything in the Elisp
>> manual), not an alist. Invalid alists will also not work on functions
>> that assume alists.
Alfred> According to M-x describe-package RET map RET:
Alfred> map.el provides generic map-manipulation functions that work on
Alfred> alists, plists, hash-tables, and arrays. All functions are
Alfred> prefixed with "map-".
Alfred> That seems like it cannot possibly work (or very complicated). How do
Alfred> you differetnate between a plist and alist? Order in an alist is
Alfred> important, but not in a plist. Their syntax is exactly the same, how
Alfred> can a insertion function work correctly for that?
map.el assumes that a list that starts with an atom is a plist, and
any other list is an alist.
That is just wrong.
alist-get and assoc obviously disagree.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Tue, 21 Jan 2025 18:49:01 GMT)
Full text and
rfc822 format available.
Message #136 received at 75170 <at> debbugs.gnu.org (full text, mbox):
Robert Pluim <rpluim <at> gmail.com> writes:
>>>>>> On Mon, 20 Jan 2025 15:40:48 -0600, Stefan Kangas <stefankangas <at> gmail.com> said:
>
> Stefan> I'm curious to hear more opinions about `map-put!`. I'm also copying in
> Stefan> Stefan Monnier, who added that function (or at least named it).
>
> map-put! does not work well with alists that are not 'proper':
>
> ELISP> (setq x (list 1 '(2 . 3)))
> (1 (2 . 3))
>
> ELISP> (map-put! x 2 4)
> 4
> (#o4, #x4, ?\C-d)
> ELISP> x
> (1 (2 . 3) 2 4)
>
> ELISP> (alist-get 2 x)
> 3
> (#o3, #x3, ?\C-c)
> ELISP> (setf (alist-get 2 x) 5)
> 5
> (#o5, #x5, ?\C-e)
> ELISP> x
> (1 (2 . 5) 2 4)
>
> If the intent is to have something thatʼs easy to use and footgun-free
> for beginners, then I donʼt think `map-put!' is it.
Thanks, I think this and the subsequent discussion shows that you're
right about that.
So `map-put!` is not a good alternative to `add-to-alist`. I don't
think generalized variables are either, not for something intended for
end-users and not developers (as `add-to-list` is).
What are we left with? Maybe we should just add `add-to-alist`.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Tue, 21 Jan 2025 18:51:02 GMT)
Full text and
rfc822 format available.
Message #139 received at 75170 <at> debbugs.gnu.org (full text, mbox):
Robert Pluim <rpluim <at> gmail.com> writes:
> map.el assumes that a list that starts with an atom is a plist, and
> any other list is an alist. alist-get and assoc obviously disagree.
This is a tangent, but I'd be curious to know how much use map.el is
getting. It doesn't seem to be too popular in emacs.git at least.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Tue, 21 Jan 2025 19:29:02 GMT)
Full text and
rfc822 format available.
Message #142 received at 75170 <at> debbugs.gnu.org (full text, mbox):
On Tue, Jan 21 2025, Eli Zaretskii wrote:
> Can someone tell me again why add-to-list doesn't fit the bill of
> being a tool easy for end-users? I've been using it in my init files
> to customize stuff like default-frame-alist since about forever.
The following was my answer from end of last year:
On Sun, Dec 29 2024, Roland Winkler wrote:
> The advantage I see for also having the function add-to-alist is the
> following:
>
> add-to-list checks for the presence of an element in a list. In the
> case of alists, this means it checks for the presence of associations.
> You cannot easily modify an existing association with add-to-list. If
> you have an alist with association (foo . bar) and you call add-to-list
> with an element (foo . baz), add-to-list will not remove the association
> (foo . bar), but the alist will then contain both associations.
>
> add-to-alist checks for the presence of keys and it makes sure that each
> key appears only once in an alist. By default, it replaces the value of
> an existing key. This makes it easy to modify an existing association.
> Only with the optional arg NO-REPLACE non-nil, it will preserve an
> existing association.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Tue, 21 Jan 2025 19:29:04 GMT)
Full text and
rfc822 format available.
Message #145 received at 75170 <at> debbugs.gnu.org (full text, mbox):
> From: Stefan Kangas <stefankangas <at> gmail.com>
> Date: Tue, 21 Jan 2025 10:47:13 -0800
> Cc: Roland Winkler <winkler <at> gnu.org>, Eli Zaretskii <eliz <at> gnu.org>, acorallo <at> gnu.org,
> 75170 <at> debbugs.gnu.org, Stefan Monnier <monnier <at> gnu.org>
>
> So `map-put!` is not a good alternative to `add-to-alist`. I don't
> think generalized variables are either, not for something intended for
> end-users and not developers (as `add-to-list` is).
>
> What are we left with? Maybe we should just add `add-to-alist`.
Can someone tell me again why add-to-list doesn't fit the bill of
being a tool easy for end-users? I've been using it in my init files
to customize stuff like default-frame-alist since about forever.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Tue, 21 Jan 2025 19:36:02 GMT)
Full text and
rfc822 format available.
Message #148 received at 75170 <at> debbugs.gnu.org (full text, mbox):
> From: Roland Winkler <winkler <at> gnu.org>
> Cc: Stefan Kangas <stefankangas <at> gmail.com>, rpluim <at> gmail.com,
> acorallo <at> gnu.org, 75170 <at> debbugs.gnu.org, monnier <at> gnu.org
> Date: Tue, 21 Jan 2025 13:21:01 -0600
>
> On Tue, Jan 21 2025, Eli Zaretskii wrote:
> > Can someone tell me again why add-to-list doesn't fit the bill of
> > being a tool easy for end-users? I've been using it in my init files
> > to customize stuff like default-frame-alist since about forever.
>
> The following was my answer from end of last year:
>
> On Sun, Dec 29 2024, Roland Winkler wrote:
> > The advantage I see for also having the function add-to-alist is the
> > following:
> >
> > add-to-list checks for the presence of an element in a list. In the
> > case of alists, this means it checks for the presence of associations.
> > You cannot easily modify an existing association with add-to-list. If
> > you have an alist with association (foo . bar) and you call add-to-list
> > with an element (foo . baz), add-to-list will not remove the association
> > (foo . bar), but the alist will then contain both associations.
> >
> > add-to-alist checks for the presence of keys and it makes sure that each
> > key appears only once in an alist. By default, it replaces the value of
> > an existing key. This makes it easy to modify an existing association.
> > Only with the optional arg NO-REPLACE non-nil, it will preserve an
> > existing association.
I know all this, but why do we think end-users who aren't comfortable
with alist-get and setf will need to "check for the presence of keys
and make sure that each key appears only once in an alist"? Since by
default add-to-list prepends the new association, those which come
after it don't matter, right?
So if we want to cater to people for whom Lisp is not a first
language, why do we think they need anything beyond add-to-list? Does
the fact that I still use add-to-list, so many years after I started
using Emacs, tell something?
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Tue, 21 Jan 2025 19:42:02 GMT)
Full text and
rfc822 format available.
Message #151 received at 75170 <at> debbugs.gnu.org (full text, mbox):
Roland Winkler <winkler <at> gnu.org> writes:
> On Tue, Jan 21 2025, Eli Zaretskii wrote:
>> Can someone tell me again why add-to-list doesn't fit the bill of
>> being a tool easy for end-users? I've been using it in my init files
>> to customize stuff like default-frame-alist since about forever.
>
> The following was my answer from end of last year:
>
> On Sun, Dec 29 2024, Roland Winkler wrote:
>> The advantage I see for also having the function add-to-alist is the
>> following:
>>
>> add-to-list checks for the presence of an element in a list. In the
>> case of alists, this means it checks for the presence of associations.
>> You cannot easily modify an existing association with add-to-list. If
>> you have an alist with association (foo . bar) and you call add-to-list
>> with an element (foo . baz), add-to-list will not remove the association
>> (foo . bar), but the alist will then contain both associations.
>>
>> add-to-alist checks for the presence of keys and it makes sure that each
>> key appears only once in an alist. By default, it replaces the value of
>> an existing key. This makes it easy to modify an existing association.
>> Only with the optional arg NO-REPLACE non-nil, it will preserve an
>> existing association.
I believe that the "contains both associations" part is what will risk
confusing some users. It's not a given that they know that the first
one is the one that will be used. It could just as easily have been the
last one, for example.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Tue, 21 Jan 2025 20:31:02 GMT)
Full text and
rfc822 format available.
Message #154 received at 75170 <at> debbugs.gnu.org (full text, mbox):
> From: Stefan Kangas <stefankangas <at> gmail.com>
> Date: Tue, 21 Jan 2025 13:41:17 -0600
> Cc: rpluim <at> gmail.com, acorallo <at> gnu.org, 75170 <at> debbugs.gnu.org, monnier <at> gnu.org
>
> >> add-to-list checks for the presence of an element in a list. In the
> >> case of alists, this means it checks for the presence of associations.
> >> You cannot easily modify an existing association with add-to-list. If
> >> you have an alist with association (foo . bar) and you call add-to-list
> >> with an element (foo . baz), add-to-list will not remove the association
> >> (foo . bar), but the alist will then contain both associations.
> >>
> >> add-to-alist checks for the presence of keys and it makes sure that each
> >> key appears only once in an alist. By default, it replaces the value of
> >> an existing key. This makes it easy to modify an existing association.
> >> Only with the optional arg NO-REPLACE non-nil, it will preserve an
> >> existing association.
>
> I believe that the "contains both associations" part is what will risk
> confusing some users. It's not a given that they know that the first
> one is the one that will be used. It could just as easily have been the
> last one, for example.
And yet add-to-list is exactly what we tell users to use, see the node
(emacs) Frame Parameters.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Tue, 21 Jan 2025 20:35:02 GMT)
Full text and
rfc822 format available.
Message #157 received at 75170 <at> debbugs.gnu.org (full text, mbox):
Eli Zaretskii <eliz <at> gnu.org> writes:
>> From: Stefan Kangas <stefankangas <at> gmail.com>
>> Date: Tue, 21 Jan 2025 13:41:17 -0600
>> Cc: rpluim <at> gmail.com, acorallo <at> gnu.org, 75170 <at> debbugs.gnu.org, monnier <at> gnu.org
>>
>> I believe that the "contains both associations" part is what will risk
>> confusing some users. It's not a given that they know that the first
>> one is the one that will be used. It could just as easily have been the
>> last one, for example.
>
> And yet add-to-list is exactly what we tell users to use, see the node
> (emacs) Frame Parameters.
I'm personally on the fence about this addition. I see good arguments
both for and against.
Given your doubts, maybe we should close this as a wontfix.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Tue, 21 Jan 2025 20:35:02 GMT)
Full text and
rfc822 format available.
Message #160 received at 75170 <at> debbugs.gnu.org (full text, mbox):
Stefan Kangas <stefankangas <at> gmail.com> writes:
> Eli Zaretskii <eliz <at> gnu.org> writes:
>
>>> From: Stefan Kangas <stefankangas <at> gmail.com>
>>> Date: Tue, 21 Jan 2025 13:41:17 -0600
>>> Cc: rpluim <at> gmail.com, acorallo <at> gnu.org, 75170 <at> debbugs.gnu.org, monnier <at> gnu.org
>>>
>>> I believe that the "contains both associations" part is what will risk
>>> confusing some users. It's not a given that they know that the first
>>> one is the one that will be used. It could just as easily have been the
>>> last one, for example.
>>
>> And yet add-to-list is exactly what we tell users to use, see the node
>> (emacs) Frame Parameters.
>
> I'm personally on the fence about this addition. I see good arguments
> both for and against.
>
> Given your doubts, maybe we should close this as a wontfix.
I sent that too soon. It should have read:
Given your doubts, and the controversy around this, maybe we should
close this as a wontfix.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Tue, 21 Jan 2025 20:58:02 GMT)
Full text and
rfc822 format available.
Message #163 received at 75170 <at> debbugs.gnu.org (full text, mbox):
> > add-to-alist checks for the presence of keys and it makes sure that each
> > key appears only once in an alist.
FWIW -
That's not an alist. At least it doesn't fit
with a common use of alists. It fits with
hash tables and similar constructs.
One of the benefits of alists is the ability
to have multiple entries with the same key,
with the first, for most purposes, shadowing
the rest.
Another use case is multiple entries with
keys that are identical for some equality
tests but not for others. "All animals are
equal, but some are more equal than others."
___
(Not saying other things you've written are
mistaken, or that it's not a good idea to
think about an `add-to-alist' function.
Just saying that entries with equal keys
are not something to be automatically
removed from alists, in general.)
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Tue, 21 Jan 2025 21:12:02 GMT)
Full text and
rfc822 format available.
Message #166 received at 75170 <at> debbugs.gnu.org (full text, mbox):
Yes, all these years later, I still use my add-to-alist.
It would be great to get this moved into Emacs proper and out
of my init file. That this issue keeps popping up says to me
that other people also would like this functionality to be
easily available.
What I like about it is how easy it is to read at the call site.
And, as has been discussed here, none of the proposed
replacements has the option to do nothing if the key is
already present (the NO-REPLACE argument). I use this option
in most of the calls in my init file, and I think it is the
compelling value-add over add-to-list.
What I don't like about the 'setf' construct is the
unintuitive textual order of the arguments: key, alist, value.
I do like that 'map-put!' puts the arguments in the order I
expect.
If we need to be able to remove an element from an alist
easily, I would want a separate function remove-from-alist.
I personally have not needed such a function.
I have updated the implementation since my old posting.
Here's my current:
(defun add-to-alist (alist-var elt-cons &optional no-replace)
"Add to the value of ALIST-VAR an element ELT-CONS if it isn't there yet.
If an element with the same car as the car of ELT-CONS is already present,
it is removed unless NO-REPLACE is non-nil, in which case ALIST-VAR is
not changed. The test for presence of the car of ELT-CONS is done
with `equal'."
(let ((existing-element (assoc (car elt-cons) (symbol-value alist-var))))
(if (or (not existing-element) (not no-replace))
(setf (alist-get (car elt-cons) (symbol-value alist-var))
(cdr elt-cons)))))
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Tue, 21 Jan 2025 22:54:01 GMT)
Full text and
rfc822 format available.
Message #169 received at 75170 <at> debbugs.gnu.org (full text, mbox):
> The test for presence of the car of ELT-CONS is done
> with `equal'."
> (assoc (car elt-cons) (symbol-value alist-var))
Seems like you should consider adding an optional
TESTFN arg for the equality predicate. There's a
reason Lisp has had both `assq' and `assoc' since
forever. And there's a reason that `assoc' itself
later began to accept such an optional arg.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Tue, 21 Jan 2025 23:09:01 GMT)
Full text and
rfc822 format available.
Message #172 received at 75170 <at> debbugs.gnu.org (full text, mbox):
I don't have much to add to this discussion except:
- I personally dislike `add-to-list` because I think that conflating
symbols with variables is a bad practice (e.g. because it is
incompatible with lexical scoping).
- Yet, it works OK for configuration, which always involves
global/dynamic variables anyway, and where `push` is not great and
`cl-pushnew` often requires `:test #'equal`.
- I think we should try and provide better support (in general) for
unloading packages, and this means improving support for undoing
top-level operations. We currently support `defalias` and friends
fairly well, `defvar` and friends tolerably, but we fail miserably for
most other things. So maybe something like an `add-to-alist` dedicated
to top-level operations, which records the change somewhere
(e.g. `load-history`) so we can undo it when unloading, would be
an improvement. Of course it would make a lot of sense to do it
together with similar operations to add an element to a list, to add
a property to a symbol, to add an advice, to add a function on a hook,
... so it's probably worth thinking of a more general way to provide
those operations than doing it one at a time.
- Stefan
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Wed, 22 Jan 2025 03:58:02 GMT)
Full text and
rfc822 format available.
Message #175 received at 75170 <at> debbugs.gnu.org (full text, mbox):
Looking at Stefan Monnier's set of things to modify and
remember for unloading, I made a list of things to extend
and the syntax for doing so:
list (add-to-list OBJECT ELEMENT)
alist (add-to-alist OBJECT (KEY . VALUE))
plist (put OBJECT KEY VALUE)
hooks (add-hook OBJECT FUNCTION)
function (define-advice OBJECT ...)
Seeing these all together, I have the following observations:
Mostly these take the name of the object as a quoted symbol.
'define-advice' doesn't require the name to be quoted, and it
also has a name starting with "def", so the leading "def" is a
good clue as to whether you need to quote the object's name.
'add-to-alist' should look more like 'put' (3 args) and less
like 'add-to-list' (2 args): (add-to-alist ALIST KEY VALUE).
We should be consistent about whether there is a "to" in the
middle of the name. 'add-to-list' and 'add-to-alist' refer to
the set we are adding to, but 'add-hook' and 'define-advice'
refer to the thing we are adding. 'put' has no noun at all;
if we add a function that supports unloading, it might be
clearer to call it 'add-to-plist'.
< Stephen
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Wed, 22 Jan 2025 05:10:02 GMT)
Full text and
rfc822 format available.
Message #178 received at 75170 <at> debbugs.gnu.org (full text, mbox):
On Tue, Jan 21 2025, Eli Zaretskii wrote:
> I know all this, but why do we think end-users who aren't comfortable
> with alist-get and setf will need to "check for the presence of keys
> and make sure that each key appears only once in an alist"? Since by
> default add-to-list prepends the new association, those which come
> after it don't matter, right?
>
> So if we want to cater to people for whom Lisp is not a first
> language, why do we think they need anything beyond add-to-list? Does
> the fact that I still use add-to-list, so many years after I started
> using Emacs, tell something?
You probably know better than almost everybody else what emacs is doing
under the hood, how individual user variables are being processed and
how changing their values in whatever way is going to change emacs'
behavior. Then, if add-to-list is doing what you want or need, that's
great. But is your level of expertise the benchmark for customizing
emacs?
I agree with Stefan K:
> I believe that the "contains both associations" part is what will risk
> confusing some users. It's not a given that they know that the first
> one is the one that will be used. It could just as easily have been the
> last one, for example.
You replied:
> And yet add-to-list is exactly what we tell users to use, see the node
> (emacs) Frame Parameters.
This quote is not about add-to-list as a feature for user init files,
but it is about default-frame-alist. It does not address what Stefan
said: with the next alist a user wants to customize, it could be the
last association for a key that will be used.
The goal of add-to-alist is to make customizing alists transparent for
non-expert users. When a user inspects an alist that has been
customized with add-to-alist, its value will be what the user expects it
to be, and not just what it can also be to achieve that purpose, if only
the first (or last) association for a key happens to be relevant.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Wed, 22 Jan 2025 05:10:02 GMT)
Full text and
rfc822 format available.
Message #181 received at 75170 <at> debbugs.gnu.org (full text, mbox):
On Tue, Jan 21 2025, Stefan Monnier wrote:
> I don't have much to add to this discussion except:
>
> - I personally dislike `add-to-list` because I think that conflating
> symbols with variables is a bad practice (e.g. because it is
> incompatible with lexical scoping).
>
> - Yet, it works OK for configuration, which always involves
> global/dynamic variables anyway, and where `push` is not great and
> `cl-pushnew` often requires `:test #'equal`.
>
> - I think we should try and provide better support (in general) for
> unloading packages, and this means improving support for undoing
> top-level operations. We currently support `defalias` and friends
> fairly well, `defvar` and friends tolerably, but we fail miserably for
> most other things. So maybe something like an `add-to-alist` dedicated
> to top-level operations, which records the change somewhere
> (e.g. `load-history`) so we can undo it when unloading, would be
> an improvement. Of course it would make a lot of sense to do it
> together with similar operations to add an element to a list, to add
> a property to a symbol, to add an advice, to add a function on a hook,
> ... so it's probably worth thinking of a more general way to provide
> those operations than doing it one at a time.
In an ideal world, the last item in your list would be great. But if
dreaming of an ideal world should imply that nothing is going to improve
in a foreseeable future, then I am in favor of less-than-ideal solutions
that can be implemented more easily.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Wed, 22 Jan 2025 08:32:03 GMT)
Full text and
rfc822 format available.
Message #184 received at 75170 <at> debbugs.gnu.org (full text, mbox):
>>>>> On Tue, 21 Jan 2025 12:50:16 -0600, Stefan Kangas <stefankangas <at> gmail.com> said:
Stefan> Robert Pluim <rpluim <at> gmail.com> writes:
>> map.el assumes that a list that starts with an atom is a plist, and
>> any other list is an alist. alist-get and assoc obviously disagree.
Stefan> This is a tangent, but I'd be curious to know how much use map.el is
Stefan> getting. It doesn't seem to be too popular in emacs.git at least.
I knew that something like `map-let' and `map-delete' existed, but
couldnʼt remember their names, and couldnʼt find them (the elisp
manual talks about 'sequences', but that covers lists and arrays, and
talks about "seq.el"). Perhaps we need to add a node to (info "(elisp)
Lists") covering "map.el"?
Also:
(defalias 'plist-delete #ʼmap-delete)
might be a good idea, to prevent people (me :-)) reinventing it.
Robert
--
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Wed, 22 Jan 2025 12:39:02 GMT)
Full text and
rfc822 format available.
Message #187 received at 75170 <at> debbugs.gnu.org (full text, mbox):
Robert Pluim <rpluim <at> gmail.com> writes:
> Perhaps we need to add a node to (info "(elisp) Lists") covering
> "map.el"?
+1.
I once tried to use map.el but gave up because of lacking documentation
(like seq.el) and docstrings I couldn't parse. This site was a relief:
https://flandrew.srht.site/listful/map-vs-other-libraries-through-hundreds-of-examples.html
Best, Arash
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Wed, 22 Jan 2025 14:07:02 GMT)
Full text and
rfc822 format available.
Message #190 received at 75170 <at> debbugs.gnu.org (full text, mbox):
> From: Stefan Kangas <stefankangas <at> gmail.com>
> Date: Tue, 21 Jan 2025 14:34:48 -0600
> Cc: winkler <at> gnu.org, rpluim <at> gmail.com, acorallo <at> gnu.org, 75170 <at> debbugs.gnu.org,
> monnier <at> gnu.org
>
> Stefan Kangas <stefankangas <at> gmail.com> writes:
>
> > Eli Zaretskii <eliz <at> gnu.org> writes:
> >
> >>> From: Stefan Kangas <stefankangas <at> gmail.com>
> >>> Date: Tue, 21 Jan 2025 13:41:17 -0600
> >>> Cc: rpluim <at> gmail.com, acorallo <at> gnu.org, 75170 <at> debbugs.gnu.org, monnier <at> gnu.org
> >>>
> >>> I believe that the "contains both associations" part is what will risk
> >>> confusing some users. It's not a given that they know that the first
> >>> one is the one that will be used. It could just as easily have been the
> >>> last one, for example.
> >>
> >> And yet add-to-list is exactly what we tell users to use, see the node
> >> (emacs) Frame Parameters.
> >
> > I'm personally on the fence about this addition. I see good arguments
> > both for and against.
> >
> > Given your doubts, maybe we should close this as a wontfix.
>
> I sent that too soon. It should have read:
>
> Given your doubts, and the controversy around this, maybe we should
> close this as a wontfix.
I don't have strong feelings or opinions, actually. Adding another
API whose name is similar to an existing one, but which works
differently (and what's worse, has different syntactic requirements),
will add to confusion and to the documentation efforts (need to go
through all the places where we currently recommend add-to-list and
change them). But if enough people insist on that...
I do still wonder why people who most certainly know about Emacs Lisp
enough to use setf/alist-git insist on adding this function to Emacs,
even though they've already solved their problem by having a private
definition for it. Why insist on adding this to Emacs? But I don't
necessarily expect an answer to that.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Wed, 22 Jan 2025 15:08:02 GMT)
Full text and
rfc822 format available.
Message #193 received at 75170 <at> debbugs.gnu.org (full text, mbox):
> From: Arash Esbati <arash <at> gnu.org>
> Cc: Stefan Kangas <stefankangas <at> gmail.com>, winkler <at> gnu.org,
> monnier <at> gnu.org, "Alfred M. Szmidt" <ams <at> gnu.org>,
> 75170 <at> debbugs.gnu.org, eliz <at> gnu.org, acorallo <at> gnu.org
> Date: Wed, 22 Jan 2025 13:38:17 +0100
>
> Robert Pluim <rpluim <at> gmail.com> writes:
>
> > Perhaps we need to add a node to (info "(elisp) Lists") covering
> > "map.el"?
>
> +1.
>
> I once tried to use map.el but gave up because of lacking documentation
> (like seq.el) and docstrings I couldn't parse.
Let's begin by fixing the doc strings, then. We can consider adding
to manual later, but the built-in documentation must be clear enough
to use map.el.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Wed, 22 Jan 2025 15:51:02 GMT)
Full text and
rfc822 format available.
Message #196 received at 75170 <at> debbugs.gnu.org (full text, mbox):
On Wed, Jan 22 2025, Eli Zaretskii wrote:
>> Robert Pluim <rpluim <at> gmail.com> writes:
>>
>> > Perhaps we need to add a node to (info "(elisp) Lists") covering
>> > "map.el"?
>>
>> +1.
>>
>> I once tried to use map.el but gave up because of lacking documentation
>> (like seq.el) and docstrings I couldn't parse.
>
> Let's begin by fixing the doc strings, then. We can consider adding
> to manual later, but the built-in documentation must be clear enough
> to use map.el.
Isn't this now a different topic? Didn't we conclude that map-put! is
not a good option to be recommended for user init files?
I like Stephen's arguments for adding add-to-alist to emacs that are
based on 20+ years of actually using it in his init file.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Wed, 22 Jan 2025 16:09:02 GMT)
Full text and
rfc822 format available.
Message #199 received at 75170 <at> debbugs.gnu.org (full text, mbox):
I like Stephen's arguments for adding add-to-alist to emacs that are
based on 20+ years of actually using it in his init file.
There are also examples of people not using it too, just because one
or two users have an idea doesn't mean that such a trivial utility
function makes sense to be added to Emacs.
What is wrong with just using add-to-list? So far it seems to be
"personal preference" and some worry that it adds keys multiple times
into the alist bucket which seems like a trivial worry, and also
.. how alists are supposed to work.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Wed, 22 Jan 2025 21:57:02 GMT)
Full text and
rfc822 format available.
Message #202 received at 75170 <at> debbugs.gnu.org (full text, mbox):
Eli Zaretskii <eliz <at> gnu.org> writes:
> Let's begin by fixing the doc strings, then. We can consider adding
> to manual later, but the built-in documentation must be clear enough
> to use map.el.
For example, I was looking at the docstring of `map-insert':
(map-insert MAP KEY VALUE)
Return a new map like MAP except that it associates KEY with VALUE.
For me, something like this would have been easier to grasp:
Cons KEY/VALUE in front of MAP replacing value associated to KEY with VALUE.
Next, I eval'ed:
(map-insert '((y . 1)) 'a 2)
=> ((a . 2) (y . 1))
(map-insert '((y . 2) (x . 1)) 'x 3)
=> ((x . 3) (y . 2) (x . 1))
And sort of gave up since I was expecting ((x . 3) (y . 2)). But again,
maybe it's just me having problems understanding the docstring.
P.S. Sorry for hijacking this thread, maybe we should move this
discussion somewhere else.
Best, Arash
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Thu, 23 Jan 2025 05:52:02 GMT)
Full text and
rfc822 format available.
Message #205 received at 75170 <at> debbugs.gnu.org (full text, mbox):
Please create a new ticket, or thread about improving map.el.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#75170
; Package
emacs
.
(Fri, 24 Jan 2025 16:40:10 GMT)
Full text and
rfc822 format available.
Message #208 received at 75170 <at> debbugs.gnu.org (full text, mbox):
On Wed, Jan 22 2025, Eli Zaretskii wrote:
> I don't have strong feelings or opinions, actually. Adding another
> API whose name is similar to an existing one, but which works
> differently (and what's worse, has different syntactic requirements),
> will add to confusion and to the documentation efforts (need to go
> through all the places where we currently recommend add-to-list and
> change them). But if enough people insist on that...
>
> I do still wonder why people who most certainly know about Emacs Lisp
> enough to use setf/alist-git insist on adding this function to Emacs,
> even though they've already solved their problem by having a private
> definition for it. Why insist on adding this to Emacs? But I don't
> necessarily expect an answer to that.
I can certainly remember my own learning curve with emacs. Only now I
can meaningfully advocate for something that would have helped me years
ago.
I can come up with a patch that also considers current recommendations
for add-to-list. Right now, I have too many other things on my plate.
But I should be able to submit a patch for review around end of next
month.
This bug report was last modified 141 days ago.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.