all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* plist-put: destructive?
@ 2017-01-20 19:13 Eric Abrahamsen
  2017-01-21  3:25 ` Stefan Monnier
  2017-01-21  8:13 ` tomas
  0 siblings, 2 replies; 14+ messages in thread
From: Eric Abrahamsen @ 2017-01-20 19:13 UTC (permalink / raw)
  To: help-gnu-emacs

Plists are great, except for setting keys, which isn't great.
Occasionally it annoys me enough to want to try to "do something" about
it.

The docstring for plist-put says we should be using:

(setq some-plist (plist-put some-plist :prop val))

To be sure of modifying the list correctly. But all my experiments have
shown that a plain plist-put does modify the original list, and
everything works as expected without re-assigning to the original
variable.

So what's the ambiguity? Are there circumstances where a simple
plist-put isn't going to modify the original plist?

I tried this:

(gv-define-simple-setter plist-get plist-put)

Which allows this to work:

(setf (plist-get some-plist :prop) val)

That's hardly less verbose than the setq re-assignment, but I suppose it
would allow for a plist to be used in cl-letf, or for a custom macro
like:

(with-plist-props ((prop1 :prop1) (prop2 :prop2)) some-plist
  ...)

But if plist-put is reliably destructive, I don't suppose any of that is
really necessary.

Can we rely on plist-put?

Thanks,
Eric




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

* Re: plist-put: destructive?
  2017-01-20 19:13 plist-put: destructive? Eric Abrahamsen
@ 2017-01-21  3:25 ` Stefan Monnier
  2017-01-21 10:25   ` tomas
  2017-01-21 16:41   ` Eric Abrahamsen
  2017-01-21  8:13 ` tomas
  1 sibling, 2 replies; 14+ messages in thread
From: Stefan Monnier @ 2017-01-21  3:25 UTC (permalink / raw)
  To: help-gnu-emacs

> So what's the ambiguity? Are there circumstances where a simple
> plist-put isn't going to modify the original plist?

Yes, when the plist is empty.
BTW, in recent Emacsen, you can use

    (setf (alist-get K AL) V)

and it works even when the alist is nil (but it requires AL to be
a valid *place* rather than an arbitrary expression).  You could make
something similar for plist-get.


        Stefan




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

* Re: plist-put: destructive?
  2017-01-20 19:13 plist-put: destructive? Eric Abrahamsen
  2017-01-21  3:25 ` Stefan Monnier
@ 2017-01-21  8:13 ` tomas
  1 sibling, 0 replies; 14+ messages in thread
From: tomas @ 2017-01-21  8:13 UTC (permalink / raw)
  To: help-gnu-emacs

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Fri, Jan 20, 2017 at 11:13:28AM -0800, Eric Abrahamsen wrote:
> Plists are great, except for setting keys, which isn't great.
> Occasionally it annoys me enough to want to try to "do something" about
> it.
> 
> The docstring for plist-put says we should be using:
> 
> (setq some-plist (plist-put some-plist :prop val))
> 
> To be sure of modifying the list correctly. But all my experiments have
> shown that a plain plist-put does modify the original list, and
> everything works as expected without re-assigning to the original
> variable.
> 
> So what's the ambiguity? Are there circumstances where a simple
> plist-put isn't going to modify the original plist?
> 
> I tried this:
> 
> (gv-define-simple-setter plist-get plist-put)
> 
> Which allows this to work:
> 
> (setf (plist-get some-plist :prop) val)
> 
> That's hardly less verbose than the setq re-assignment, but I suppose it
> would allow for a plist to be used in cl-letf, or for a custom macro
> like:
> 
> (with-plist-props ((prop1 :prop1) (prop2 :prop2)) some-plist
>   ...)
> 
> But if plist-put is reliably destructive, I don't suppose any of that is
> really necessary.
> 
> Can we rely on plist-put?

Try starting with an empty plist

(IOW: plist-put is destructive if it has something to tack the new pair
on. Otherwise it can't. Perhaps the above if can be made into an iff)

regards
- -- t
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (GNU/Linux)

iEYEARECAAYFAliDGBUACgkQBcgs9XrR2kYH4QCfaayFmENHeH8Hsai9zWhJoGZ/
a3gAn1BMdM4EKJAS+cEkaNUmKavWu3hj
=uxIG
-----END PGP SIGNATURE-----



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

* Re: plist-put: destructive?
  2017-01-21  3:25 ` Stefan Monnier
@ 2017-01-21 10:25   ` tomas
  2017-01-21 16:41   ` Eric Abrahamsen
  1 sibling, 0 replies; 14+ messages in thread
From: tomas @ 2017-01-21 10:25 UTC (permalink / raw)
  To: help-gnu-emacs

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Fri, Jan 20, 2017 at 10:25:27PM -0500, Stefan Monnier wrote:
> > So what's the ambiguity? Are there circumstances where a simple
> > plist-put isn't going to modify the original plist?
> 
> Yes, when the plist is empty.
> BTW, in recent Emacsen, you can use
> 
>     (setf (alist-get K AL) V)

Now that's deliciously nifty :-)

Thanks for the reminder
- -- t
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (GNU/Linux)

iEYEARECAAYFAliDNyIACgkQBcgs9XrR2kZ2hQCfZS84VePEE6ZIizJC4vE8ZYZh
w4IAn1pBRlrUvAOpaEmLYZNvZlgv5JAt
=qwjk
-----END PGP SIGNATURE-----



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

* Re: plist-put: destructive?
  2017-01-21  3:25 ` Stefan Monnier
  2017-01-21 10:25   ` tomas
@ 2017-01-21 16:41   ` Eric Abrahamsen
  2017-01-21 17:13     ` Drew Adams
  2017-01-21 23:03     ` Stefan Monnier
  1 sibling, 2 replies; 14+ messages in thread
From: Eric Abrahamsen @ 2017-01-21 16:41 UTC (permalink / raw)
  To: help-gnu-emacs

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>> So what's the ambiguity? Are there circumstances where a simple
>> plist-put isn't going to modify the original plist?
>
> Yes, when the plist is empty.

Thanks to you both. I'm working with existing plists, so I'll drop the
setqs, that's a relief.

> BTW, in recent Emacsen, you can use
>
>     (setf (alist-get K AL) V)
>
> and it works even when the alist is nil (but it requires AL to be
> a valid *place* rather than an arbitrary expression).  You could make
> something similar for plist-get.

Making something similar would just be the `gv-define-simple-setter'
call I had in the original message, right?




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

* RE: plist-put: destructive?
  2017-01-21 16:41   ` Eric Abrahamsen
@ 2017-01-21 17:13     ` Drew Adams
  2017-01-22  0:50       ` Eric Abrahamsen
  2017-01-21 23:03     ` Stefan Monnier
  1 sibling, 1 reply; 14+ messages in thread
From: Drew Adams @ 2017-01-21 17:13 UTC (permalink / raw)
  To: Eric Abrahamsen, help-gnu-emacs

> Thanks to you both. I'm working with existing plists, so I'll drop
> the setqs, that's a relief.

Why is it a relief - a relief from what?  What if something reset your "existing plist" to nil behind your back?

Setting (again) a variable whose value is an object to which you've applied a destructive operation is the standard idiom.  And it is good programming practice.  It ensures that your code does what you expect, regardless of the object value, or rather, regardless of the effect of the operation.

You naturally think of your variable as always pointing to the object that you expect.  To keep this relationship, you must set the variable to the return value of any destructive operation.

This is true for a possibly "destructive" operation on any kind of object.  The poster-child case is a list.  See, for example, (elisp) `Rearrangement' (http://www.gnu.org/software/emacs/manual/html_node/elisp/Rearrangement.html).

The point is that your variable is otherwise not guaranteed to continue to point to the object that you think it does.  You need to set it to the _result_ of the possibly destructive operation (the return value), if you really want the variable to take the effect of that operation into account.

This is all about the difference between a variable and its object value.



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

* Re: plist-put: destructive?
  2017-01-21 16:41   ` Eric Abrahamsen
  2017-01-21 17:13     ` Drew Adams
@ 2017-01-21 23:03     ` Stefan Monnier
  2017-01-22  1:15       ` Eric Abrahamsen
  1 sibling, 1 reply; 14+ messages in thread
From: Stefan Monnier @ 2017-01-21 23:03 UTC (permalink / raw)
  To: help-gnu-emacs

> Making something similar would just be the `gv-define-simple-setter'
> call I had in the original message, right?

Not if we want it to be reliable in the presence of empty plists.


        Stefan




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

* Re: plist-put: destructive?
  2017-01-21 17:13     ` Drew Adams
@ 2017-01-22  0:50       ` Eric Abrahamsen
  2017-01-22 10:08         ` Philipp Stephani
  2017-01-22 17:30         ` Stefan Monnier
  0 siblings, 2 replies; 14+ messages in thread
From: Eric Abrahamsen @ 2017-01-22  0:50 UTC (permalink / raw)
  To: help-gnu-emacs

Drew Adams <drew.adams@oracle.com> writes:

>> Thanks to you both. I'm working with existing plists, so I'll drop
>> the setqs, that's a relief.
>
> Why is it a relief - a relief from what?  What if something reset your "existing plist" to nil behind your back?

The code I'm working has many repeated clauses looking like:

(when thing1
  (setq the-plist (plist-put the-plist :thing thing1)))

A little more complicated than that, but there will be like seven of
those in a row. Probably I should just write myself a custom
bulk-conditional-plist-setter macro, probably using the gv setter, but
for the time being just being able to remove all the "(setq the-plist"
makes everything easier to read.

> Setting (again) a variable whose value is an object to which you've
> applied a destructive operation is the standard idiom. And it is good
> programming practice. It ensures that your code does what you expect,
> regardless of the object value, or rather, regardless of the effect of
> the operation.
>
> You naturally think of your variable as always pointing to the object that you expect.  To keep this relationship, you must set the variable to the return value of any destructive operation.
>
> This is true for a possibly "destructive" operation on any kind of object.  The poster-child case is a list.  See, for example, (elisp) `Rearrangement' (http://www.gnu.org/software/emacs/manual/html_node/elisp/Rearrangement.html).
>
> The point is that your variable is otherwise not guaranteed to
> continue to point to the object that you think it does. You need to
> set it to the _result_ of the possibly destructive operation (the
> return value), if you really want the variable to take the effect of
> that operation into account.
>
> This is all about the difference between a variable and its object value.

I understand the difference, but in this particular case I'm willing to
drop the setqs.

Eric




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

* Re: plist-put: destructive?
  2017-01-21 23:03     ` Stefan Monnier
@ 2017-01-22  1:15       ` Eric Abrahamsen
  0 siblings, 0 replies; 14+ messages in thread
From: Eric Abrahamsen @ 2017-01-22  1:15 UTC (permalink / raw)
  To: help-gnu-emacs

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>> Making something similar would just be the `gv-define-simple-setter'
>> call I had in the original message, right?
>
> Not if we want it to be reliable in the presence of empty plists.

Ah, I see.




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

* Re: plist-put: destructive?
  2017-01-22  0:50       ` Eric Abrahamsen
@ 2017-01-22 10:08         ` Philipp Stephani
  2017-01-22 13:10           ` Eric Abrahamsen
  2017-01-22 17:30         ` Stefan Monnier
  1 sibling, 1 reply; 14+ messages in thread
From: Philipp Stephani @ 2017-01-22 10:08 UTC (permalink / raw)
  To: Eric Abrahamsen, help-gnu-emacs

Eric Abrahamsen <eric@ericabrahamsen.net> schrieb am So., 22. Jan. 2017 um
01:57 Uhr:

> Drew Adams <drew.adams@oracle.com> writes:
>
> >> Thanks to you both. I'm working with existing plists, so I'll drop
> >> the setqs, that's a relief.
> >
> > Why is it a relief - a relief from what?  What if something reset your
> "existing plist" to nil behind your back?
>
> The code I'm working has many repeated clauses looking like:
>
> (when thing1
>   (setq the-plist (plist-put the-plist :thing thing1)))
>
> A little more complicated than that, but there will be like seven of
> those in a row. Probably I should just write myself a custom
> bulk-conditional-plist-setter macro, probably using the gv setter, but
> for the time being just being able to remove all the "(setq the-plist"
> makes everything easier to read.
>

 You could also write
(cl-callf plist-put the-plist :thing thing1)


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

* Re: plist-put: destructive?
  2017-01-22 10:08         ` Philipp Stephani
@ 2017-01-22 13:10           ` Eric Abrahamsen
  0 siblings, 0 replies; 14+ messages in thread
From: Eric Abrahamsen @ 2017-01-22 13:10 UTC (permalink / raw)
  To: help-gnu-emacs

Philipp Stephani <p.stephani2@gmail.com> writes:

> Eric Abrahamsen <eric@ericabrahamsen.net> schrieb am So., 22. Jan. 2017 um
> 01:57 Uhr:
>
>> Drew Adams <drew.adams@oracle.com> writes:
>>
>> >> Thanks to you both. I'm working with existing plists, so I'll drop
>> >> the setqs, that's a relief.
>> >
>> > Why is it a relief - a relief from what?  What if something reset your
>> "existing plist" to nil behind your back?
>>
>> The code I'm working has many repeated clauses looking like:
>>
>> (when thing1
>>   (setq the-plist (plist-put the-plist :thing thing1)))
>>
>> A little more complicated than that, but there will be like seven of
>> those in a row. Probably I should just write myself a custom
>> bulk-conditional-plist-setter macro, probably using the gv setter, but
>> for the time being just being able to remove all the "(setq the-plist"
>> makes everything easier to read.
>>
>
>  You could also write
> (cl-callf plist-put the-plist :thing thing1)

Thanks, that was a new one for me!




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

* Re: plist-put: destructive?
  2017-01-22  0:50       ` Eric Abrahamsen
  2017-01-22 10:08         ` Philipp Stephani
@ 2017-01-22 17:30         ` Stefan Monnier
  2017-01-23  0:31           ` Eric Abrahamsen
  2017-01-23  9:01           ` tomas
  1 sibling, 2 replies; 14+ messages in thread
From: Stefan Monnier @ 2017-01-22 17:30 UTC (permalink / raw)
  To: help-gnu-emacs

> The code I'm working has many repeated clauses looking like:
>
> (when thing1
>   (setq the-plist (plist-put the-plist :thing thing1)))

FWIW, I've found that such code can often advantageously be turned
into a non-side-effecting form like:

   (let ((the-plist
          (nconc
           (when thing1 (list :key1 thing1))
           (when thing2 (list :key2 thing2))
           ...)))


-- Stefan




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

* Re: plist-put: destructive?
  2017-01-22 17:30         ` Stefan Monnier
@ 2017-01-23  0:31           ` Eric Abrahamsen
  2017-01-23  9:01           ` tomas
  1 sibling, 0 replies; 14+ messages in thread
From: Eric Abrahamsen @ 2017-01-23  0:31 UTC (permalink / raw)
  To: help-gnu-emacs

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>> The code I'm working has many repeated clauses looking like:
>>
>> (when thing1
>>   (setq the-plist (plist-put the-plist :thing thing1)))
>
> FWIW, I've found that such code can often advantageously be turned
> into a non-side-effecting form like:
>
>    (let ((the-plist
>           (nconc
>            (when thing1 (list :key1 thing1))
>            (when thing2 (list :key2 thing2))
>            ...)))

I wouldn't have thought of that, thanks! I need to get more familiar
with the lower-level list-manipulation stuff, I never think to reach for
them...




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

* Re: plist-put: destructive?
  2017-01-22 17:30         ` Stefan Monnier
  2017-01-23  0:31           ` Eric Abrahamsen
@ 2017-01-23  9:01           ` tomas
  1 sibling, 0 replies; 14+ messages in thread
From: tomas @ 2017-01-23  9:01 UTC (permalink / raw)
  To: help-gnu-emacs

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Sun, Jan 22, 2017 at 12:30:49PM -0500, Stefan Monnier wrote:
> > The code I'm working has many repeated clauses looking like:
> >
> > (when thing1
> >   (setq the-plist (plist-put the-plist :thing thing1)))
> 
> FWIW, I've found that such code can often advantageously be turned
> into a non-side-effecting form like:
> 
>    (let ((the-plist
>           (nconc
>            (when thing1 (list :key1 thing1))
>            (when thing2 (list :key2 thing2))
>            ...)))

Thanks for this one! I positively know I've been struggling for
something like that, only to come up with a far clumsier variant.

- -- t
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (GNU/Linux)

iEYEARECAAYFAliFxnsACgkQBcgs9XrR2kY82wCfboH2ToyZGcsOaoFCB1zuqxQ/
5hoAn3gM7xvUAvQfZSr7CH9+wCeDxRDn
=hZBt
-----END PGP SIGNATURE-----



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

end of thread, other threads:[~2017-01-23  9:01 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-01-20 19:13 plist-put: destructive? Eric Abrahamsen
2017-01-21  3:25 ` Stefan Monnier
2017-01-21 10:25   ` tomas
2017-01-21 16:41   ` Eric Abrahamsen
2017-01-21 17:13     ` Drew Adams
2017-01-22  0:50       ` Eric Abrahamsen
2017-01-22 10:08         ` Philipp Stephani
2017-01-22 13:10           ` Eric Abrahamsen
2017-01-22 17:30         ` Stefan Monnier
2017-01-23  0:31           ` Eric Abrahamsen
2017-01-23  9:01           ` tomas
2017-01-21 23:03     ` Stefan Monnier
2017-01-22  1:15       ` Eric Abrahamsen
2017-01-21  8:13 ` tomas

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.