all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* 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.