unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: "Drew Adams" <drew.adams@oracle.com>
To: "'Eli Zaretskii'" <eliz@gnu.org>
Cc: 12314@debbugs.gnu.org, cyd@gnu.org
Subject: bug#12314: 24.2.50; `add-to-history': use `setq' with `delete'
Date: Sat, 8 Sep 2012 08:48:53 -0700	[thread overview]
Message-ID: <9A8F619FD7584123A6319BD089E444E4@us.oracle.com> (raw)
In-Reply-To: <83fw6smti6.fsf@gnu.org>

> That for a list, assigning the result is not necessary.  At least
> that's my interpretation of what the manual says.

No, that is incorrect.  This is an old Lisp gotcha.  It is one reason people
often advise Lisp newbies not to start out by using destructive operations.
They can be quite confusing, and you can run into trouble far from where a
problem/bug is introduced.

> > Keep reading the same section of the manual (section for `delete'):
> > 
> >   ;; If you want to change `l' reliably,
> >   ;; write `(setq l (delete '(2) l))'.
> 
> My interpretation of "reliably" here is "without assuming that l is a
> list".  Is that a wrong interpretation?

Yes, it is wrong.

> > There is more explanation higher up in the same node, under `delq':
> 
> 'delq' is not identical to 'delete', so assumptions that somethiong
> described there is pertinent to 'delete' are unsafe.  And how should
> the reader know that she needs to read something under 'delq' to fully
> understand what 'delete' does, anyway?

The doc for `delete' sends you to the doc for `delq', where there is a good
step-by-step illustration.  The only difference between `delq' and `delete' is
comparison by `eq' vs by `equal'.

This is in fact a general thing for Lisp functions that are destructive of list
structure.

The manual describes it for `delq':

 When `delq' deletes elements from the front of the list, it
 does so simply by advancing down the list and returning a
 sublist that starts after those elements:

     (delq 'a '(a b c)) == (cdr '(a b c))

The point is not to confuse the _side effect_ of an operation (so-called
"function") such as `delete' with its _return value_.

The list targeted by the function might or might not be modified.  The return
value has the correct contents in all cases, and that is why you should
generally set your variable to the return value, if you want that variable to
reflect the result of the operation.

The list structure is one thing.  Your variable pointing to some list structure
is another thing.  If you want the variable to reflect the changed structure
(list contents) in all cases, then set the variable value to the function's
return value.

In short, to reflect the _result_ of the operation, you need to set the variable
to the returned result.  Otherwise, it will not necessarily point to a list that
has the correct contents.

> I'm not sure who is missing what.  All I'm saying is that the manual
> seems to suggest that an explicit assignment is unnecessary, and yet
> Chong did exactly that.  If just "(delete 'foo bar)", with 'bar' a
> list, is sometimes not enough, the manual should say when.  And if it
> is enough, why should we make the change in add-to-history?

It is not enough, if you need the variable to reflect the updated list contents.
It's about using the return value of the function vs depending on the "function"
only for its side effect (i.e., not caring about what the variable points to
after the operation).

If we cared only about a particular list structure and not some variable that
might point to it, then we might not bother to update the variable by setting it
to the returned value.

> IOW, it sounds like some kind of black magic is going on under the
> hood, but the manual is too shy to talk about it.  It shouldn't; doing
> so could easily spread confusion.  I'm not sure the code in question
> was written as it was due to that confusion.

It's not black magic, but it is about list structure and Lisp not being a
(purely) functional language.

Perhaps the node `Modifying Lists' should go into a little more detail about
this; dunno.  `delq' or `delete' is a great way to illustrate it, and we
currently do that (for `delq').  Perhaps we should be more explicit about other
list-modifying (i.e. destructive) operations having the same behavior, and
generally advise setting any variable you care about to the returned value of
the function.






  reply	other threads:[~2012-09-08 15:48 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-08-30 23:08 bug#12314: 24.2.50; `add-to-history': use `setq' with `delete' Drew Adams
2012-09-08 14:32 ` Chong Yidong
2012-09-08 14:43   ` Eli Zaretskii
2012-09-08 14:57     ` Drew Adams
2012-09-08 15:20       ` Eli Zaretskii
2012-09-08 15:48         ` Drew Adams [this message]
2012-09-08 16:05           ` Eli Zaretskii
2012-09-08 16:19             ` Andreas Schwab
2012-09-08 16:33               ` Eli Zaretskii
2012-09-08 16:50                 ` Lars Ingebrigtsen
2012-09-08 16:54                 ` Drew Adams
2012-09-08 17:06                 ` Andreas Schwab
2012-09-08 16:35               ` Drew Adams
2012-09-08 16:25             ` Drew Adams
2012-09-08 16:32               ` Eli Zaretskii
2012-09-08 16:42                 ` Drew Adams
2012-09-08 21:21                   ` Eli Zaretskii
2012-09-08 22:26                     ` Drew Adams
2012-09-09  3:00                       ` Eli Zaretskii
2012-09-09  6:29                         ` Drew Adams
2012-09-09  7:53                         ` Chong Yidong
2012-09-09 17:25                           ` Eli Zaretskii
2012-09-10 11:54                       ` Wolfgang Jenkner
2012-09-08 23:11                     ` Stefan Monnier
2012-09-09  2:51                       ` Eli Zaretskii
2012-09-09 14:44                         ` Stefan Monnier
2012-09-09 17:14                           ` Eli Zaretskii
2012-09-09 17:35                             ` Drew Adams
2012-09-09 18:20                               ` Eli Zaretskii
2012-09-09 19:46                                 ` Drew Adams
2012-09-09 21:37                             ` Stefan Monnier
2012-09-10  4:37                               ` Eli Zaretskii
2012-09-10 12:59                                 ` Stefan Monnier
2012-09-10 15:01                                   ` Stefan Monnier
2012-09-10 15:21                                   ` Drew Adams
2012-09-10 16:24                                   ` Eli Zaretskii
2012-09-09  8:25 ` Dmitry Gutov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=9A8F619FD7584123A6319BD089E444E4@us.oracle.com \
    --to=drew.adams@oracle.com \
    --cc=12314@debbugs.gnu.org \
    --cc=cyd@gnu.org \
    --cc=eliz@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).