* bug#62117: 29.0.60; cl-letf on a map place has side-effects
@ 2023-03-11 7:44 Augusto Stoffel
2023-03-12 0:00 ` Michael Heerdegen
0 siblings, 1 reply; 4+ messages in thread
From: Augusto Stoffel @ 2023-03-11 7:44 UTC (permalink / raw)
To: 62117
Consider this example:
--8<---------------cut here---------------start------------->8---
(require 'cl-lib)
(defun f (map)
(cl-letf (((map-elt map 'a) 1))
map))
(let ((map '(b 2)))
(f map)
map)
=> (b 2 a nil)
(let ((map (make-hash-table)))
(f map)
(map-length map))
=> 1
--8<---------------cut here---------------end--------------->8---
I would expect `f' to have no side effects, so get (b 2) and 0
respectively in the two examples.
For comparison, plist-get as a place has no side-effect:
--8<---------------cut here---------------start------------->8---
(defun g (map)
(cl-letf (((plist-get map 'a) 1))
map))
(let ((map '(b 2)))
(g map)
map)
(b 2)
--8<---------------cut here---------------end--------------->8---
Of course it's usual to treat a nil entry and no entry as equivalent in
Lisp, but this behavior can be a problem e.g. when constructing data to
pass to other programs.
^ permalink raw reply [flat|nested] 4+ messages in thread
* bug#62117: 29.0.60; cl-letf on a map place has side-effects
2023-03-11 7:44 bug#62117: 29.0.60; cl-letf on a map place has side-effects Augusto Stoffel
@ 2023-03-12 0:00 ` Michael Heerdegen
2023-03-12 6:09 ` Augusto Stoffel
0 siblings, 1 reply; 4+ messages in thread
From: Michael Heerdegen @ 2023-03-12 0:00 UTC (permalink / raw)
To: Augusto Stoffel; +Cc: 62117
Augusto Stoffel <arstoffel@gmail.com> writes:
> Consider this example:
>
> (require 'cl-lib)
> (defun f (map)
> (cl-letf (((map-elt map 'a) 1))
> map))
>
> (let ((map '(b 2)))
> (f map)
> map)
> => (b 2 a nil)
>
> (let ((map (make-hash-table)))
> (f map)
> (map-length map))
> => 1
>
>
> I would expect `f' to have no side effects, so get (b 2) and 0
> respectively in the two examples.
This is a symptom of a general limitation of `cl-letf'. Currently you can't
rely on a "no side effect" behavior. There are other examples like that
(`alist-get') and cases that are worse (binding `buffer-local-value' of
a variable in a buffer with no buffer local binding doesn't remove the
buffer-localness - that's one reason why that gv had been deprecated).
> Of course it's usual to treat a nil entry and no entry as equivalent in
> Lisp, but this behavior can be a problem e.g. when constructing data to
> pass to other programs.
I would say: if it is a problem, map.el is the wrong abstraction for
your case. That's the genuine idea of map.el: that the inner structure
of a map doesn't matter.
So I would close this one - unless you have some enlightening idea that
would be an obvious improvement with no downsides and backward
compatibility problems.
Thanks,
Michael.
^ permalink raw reply [flat|nested] 4+ messages in thread
* bug#62117: 29.0.60; cl-letf on a map place has side-effects
2023-03-12 0:00 ` Michael Heerdegen
@ 2023-03-12 6:09 ` Augusto Stoffel
2023-03-15 2:13 ` Michael Heerdegen
0 siblings, 1 reply; 4+ messages in thread
From: Augusto Stoffel @ 2023-03-12 6:09 UTC (permalink / raw)
To: Michael Heerdegen; +Cc: 62117
On Sun, 12 Mar 2023 at 01:00, Michael Heerdegen wrote:
> Augusto Stoffel <arstoffel@gmail.com> writes:
> This is a symptom of a general limitation of `cl-letf'. Currently you can't
> rely on a "no side effect" behavior. There are other examples like that
> (`alist-get') and cases that are worse (binding `buffer-local-value' of
> a variable in a buffer with no buffer local binding doesn't remove the
> buffer-localness - that's one reason why that gv had been deprecated).
Right, so let's drop this bug.
>> Of course it's usual to treat a nil entry and no entry as equivalent in
>> Lisp, but this behavior can be a problem e.g. when constructing data to
>> pass to other programs.
>
> I would say: if it is a problem, map.el is the wrong abstraction for
> your case. That's the genuine idea of map.el: that the inner structure
> of a map doesn't matter.
This is not right. map.el doesn't abstract away the nil entries. They
make a difference all over, e.g. in map-length, map-do, map-empty-p...
^ permalink raw reply [flat|nested] 4+ messages in thread
* bug#62117: 29.0.60; cl-letf on a map place has side-effects
2023-03-12 6:09 ` Augusto Stoffel
@ 2023-03-15 2:13 ` Michael Heerdegen
0 siblings, 0 replies; 4+ messages in thread
From: Michael Heerdegen @ 2023-03-15 2:13 UTC (permalink / raw)
To: Augusto Stoffel; +Cc: 62117
Augusto Stoffel <arstoffel@gmail.com> writes:
> >> Of course it's usual to treat a nil entry and no entry as equivalent in
> >> Lisp, but this behavior can be a problem e.g. when constructing data to
> >> pass to other programs.
> >
> > I would say: if it is a problem, map.el is the wrong abstraction for
> > your case. That's the genuine idea of map.el: that the inner structure
> > of a map doesn't matter.
>
> This is not right. map.el doesn't abstract away the nil entries. They
> make a difference all over, e.g. in map-length, map-do, map-empty-p...
Hmm - right, of course.
For your original recipe, it would in theory help if the implementation
of `map-put!' for hash tables would remove the entry if the set value is
nil. But for the reason you gave, we probably don't want to do this.
Unless maybe we do the same thing that had been done for `alist-get'
and add an additional REMOVE argument to the generic functions `map-elt'
and `map-put!' (I'm afraid that a lot of people that like using
libraries such as map.el don't like using such an argument, though).
`cl-letf' would still not be smart enough to distinguish the two cases
(1) value was the default value and (2) there was no entry when
restoring the gv binding.
Michael.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2023-03-15 2:13 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-03-11 7:44 bug#62117: 29.0.60; cl-letf on a map place has side-effects Augusto Stoffel
2023-03-12 0:00 ` Michael Heerdegen
2023-03-12 6:09 ` Augusto Stoffel
2023-03-15 2:13 ` Michael Heerdegen
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.