Subject: Re: [DOC] modify literal objects
From: Paul Eggert <[email-masked]>
To: Mattias Engdegård <[email-masked]>
Cc: Kevin Vigouroux <[email-masked]>, Eli Zaretskii <[email-masked]>, [email-masked]
Date: Sat, 18 Apr 2020 13:10:30 -0700
List-Id: <debbugs-submit.debbugs.gnu.org>

Mattias, thanks for going through the Emacs manual and looking for mistakes in 
this area. I know it was a pain to do that, since I did something similar in 
parallel and it was painful for me. I used your patch to crosscheck with my 
draft (finding omissions on both sides) and installed the resulting patch 
(attached) into the emacs-27 branch.

This patch should address the points that Eli raised. That is, it adds 
explanations of the issue (both in the intro and the reference manual, since the 
issue also infects the intro), and it attempts to change examples only when the 
changes are needed to avoid undefined behavior in Emacs Lisp. I also kept the 
changes from '< to #'< that were in your patch since that's good style.
From eebfb72c906755c0a80d92c11deee7ac9faf5f4b Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Sat, 18 Apr 2020 12:59:17 -0700
Subject: [PATCH] Document constant vs mutable objects better
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This patch builds on a suggested patch by Mattias Engdegård
and on further comments by Eli Zaretskii.
Original bug report by Kevin Vigouroux (Bug#40671).
* doc/lispintro/emacs-lisp-intro.texi (set & setq, Review)
(setcar, Lists diagrammed, Mail Aliases, Indent Tabs Mode):
setq is a special form, not a function or command.
* doc/lispintro/emacs-lisp-intro.texi (setcar):
* doc/lispref/lists.texi (Modifying Lists, Rearrangement):
* doc/lispref/sequences.texi (Sequence Functions)
(Array Functions, Vectors):
* doc/lispref/strings.texi (String Basics, Modifying Strings):
Mention mutable vs constant objects.
* doc/lispintro/emacs-lisp-intro.texi (setcar, setcdr)
(kill-new function, cons & search-fwd Review):
* doc/lispref/edebug.texi (Printing in Edebug):
* doc/lispref/keymaps.texi (Changing Key Bindings):
* doc/lispref/lists.texi (Setcar, Setcdr, Rearrangement)
(Sets And Lists, Association Lists, Plist Access):
* doc/lispref/sequences.texi (Sequence Functions)
(Array Functions):
* doc/lispref/strings.texi (Text Comparison):
Fix examples so that they do not try to change constants.
---
 doc/lispintro/emacs-lisp-intro.texi | 32 +++++++++------
 doc/lispref/edebug.texi             |  2 +-
 doc/lispref/keymaps.texi            |  8 ++--
 doc/lispref/lists.texi              | 60 +++++++++++++++++------------
 doc/lispref/sequences.texi          | 31 +++++++++------
 doc/lispref/strings.texi            | 17 +++++---
 6 files changed, 91 insertions(+), 59 deletions(-)

diff --git a/doc/lispintro/emacs-lisp-intro.texi b/doc/lispintro/emacs-lisp-intro.texi
index bd688070a3..630676d978 100644
--- a/doc/lispintro/emacs-lisp-intro.texi
+++ b/doc/lispintro/emacs-lisp-intro.texi
@@ -2329,7 +2329,7 @@ area.
 
 @cindex @samp{bind} defined
 There are several ways by which a variable can be given a value.  One of
-the ways is to use either the function @code{set} or the function
+the ways is to use either the function @code{set} or the special form
 @code{setq}.  Another way is to use @code{let} (@pxref{let}).  (The
 jargon for this process is to @dfn{bind} a variable to a value.)
 
@@ -4517,7 +4517,7 @@ number; it will be printed as the character with that @sc{ascii} code.
 
 @item setq
 @itemx set
-The @code{setq} function sets the value of its first argument to the
+The @code{setq} special form sets the value of its first argument to the
 value of the second argument.  The first argument is automatically
 quoted by @code{setq}.  It does the same for succeeding pairs of
 arguments.  Another function, @code{set}, takes only two arguments and
@@ -7317,11 +7317,21 @@ which leave the original list as it was.  One way to find out how this
 works is to experiment.  We will start with the @code{setcar} function.
 
 @need 1200
+@cindex constant lists
+@cindex mutable lists
 First, we can make a list and then set the value of a variable to the
-list, using the @code{setq} function.  Here is a list of animals:
+list, using the @code{setq} special form.  Because we intend to use
+@code{setcar} to change the list, this @code{setq} should not use the
+quoted form @code{'(antelope giraffe lion tiger)}, as that would yield
+a list that is part of the program and bad things could happen if we
+tried to change part of the program while running it.  Generally
+speaking an Emacs Lisp program's components should be constant (or
+unchanged) while the program is running.  So we instead construct an
+animal list that is @dfn{mutable} (or changeable) by using the
+@code{list} function, as follows:
 
 @smallexample
-(setq animals '(antelope giraffe lion tiger))
+(setq animals (list 'antelope 'giraffe 'lion 'tiger))
 @end smallexample
 
 @noindent
@@ -7398,7 +7408,7 @@ To see how this works, set the value of the variable to a list of
 domesticated animals by evaluating the following expression:
 
 @smallexample
-(setq domesticated-animals '(horse cow sheep goat))
+(setq domesticated-animals (list 'horse 'cow 'sheep 'goat))
 @end smallexample
 
 @need 1200
@@ -8846,7 +8856,7 @@ and then find the value of @code{trees}:
 
 @smallexample
 @group
-(setq trees '(maple oak pine birch))
+(setq trees (list 'maple 'oak 'pine 'birch))
      @result{} (maple oak pine birch)
 @end group
 
@@ -9366,7 +9376,7 @@ For example:
 
 @smallexample
 @group
-(setq triple '(1 2 3))
+(setq triple (list 1 2 3))
 
 (setcar triple '37)
 
@@ -9547,7 +9557,7 @@ part of which is the address of the next pair.  The very last box
 points to the symbol @code{nil}, which marks the end of the list.
 
 @need 1200
-When a variable is set to a list with a function such as @code{setq},
+When a variable is set to a list via @code{setq},
 it stores the address of the first box in the variable.  Thus,
 evaluation of the expression
 
@@ -17092,7 +17102,7 @@ reminders.
 
 @cindex Mail aliases
 @noindent
-This @code{setq} command sets the value of the variable
+This @code{setq} sets the value of the variable
 @code{mail-aliases} to @code{t}.  Since @code{t} means true, the line
 says, in effect, ``Yes, use mail aliases.''
 
@@ -17130,8 +17140,8 @@ The following turns off Indent Tabs mode:
 @end smallexample
 
 Note that this line uses @code{setq-default} rather than the
-@code{setq} command that we have seen before.  The @code{setq-default}
-command sets values only in buffers that do not have their own local
+@code{setq} that we have seen before.  The @code{setq-default}
+sets values only in buffers that do not have their own local
 values for the variable.
 
 @ifinfo
diff --git a/doc/lispref/edebug.texi b/doc/lispref/edebug.texi
index 8be8307c75..ec76e83db1 100644
--- a/doc/lispref/edebug.texi
+++ b/doc/lispref/edebug.texi
@@ -858,7 +858,7 @@ to a non-@code{nil} value.
   Here is an example of code that creates a circular structure:
 
 @example
-(setq a '(x y))
+(setq a (list 'x 'y))
 (setcar a a)
 @end example
 
diff --git a/doc/lispref/keymaps.texi b/doc/lispref/keymaps.texi
index c6a02d721f..4db9969767 100644
--- a/doc/lispref/keymaps.texi
+++ b/doc/lispref/keymaps.texi
@@ -1441,10 +1441,10 @@ Here is an example showing a keymap before and after substitution:
 
 @smallexample
 @group
-(setq map '(keymap
-            (?1 . olddef-1)
-            (?2 . olddef-2)
-            (?3 . olddef-1)))
+(setq map (list 'keymap
+                (cons ?1 olddef-1)
+                (cons ?2 olddef-2)
+                (cons ?3 olddef-1)))
 @result{} (keymap (49 . olddef-1) (50 . olddef-2) (51 . olddef-1))
 @end group
 
diff --git a/doc/lispref/lists.texi b/doc/lispref/lists.texi
index 27fa5385e3..c2771b0165 100644
--- a/doc/lispref/lists.texi
+++ b/doc/lispref/lists.texi
@@ -866,10 +866,16 @@ foo                       ;; @r{@code{foo} was changed.}
 @node Modifying Lists
 @section Modifying Existing List Structure
 @cindex destructive list operations
+@cindex constant lists
+@cindex mutable lists
 
   You can modify the @sc{car} and @sc{cdr} contents of a cons cell with the
 primitives @code{setcar} and @code{setcdr}.  These are destructive
 operations because they change existing list structure.
+Destructive operations should be applied only to @dfn{mutable} lists,
+that is, lists constructed via @code{cons}, @code{list} or similar
+operations.  Lists created by quoting are constants and should not be
+changed by destructive operations.
 
 @cindex CL note---@code{rplaca} vs @code{setcar}
 @quotation
@@ -906,7 +912,7 @@ value @var{object}.  For example:
 
 @example
 @group
-(setq x '(1 2))
+(setq x (list 1 2))
      @result{} (1 2)
 @end group
 @group
@@ -927,7 +933,7 @@ these lists.  Here is an example:
 @example
 @group
 ;; @r{Create two lists that are partly shared.}
-(setq x1 '(a b c))
+(setq x1 (list 'a 'b 'c))
      @result{} (a b c)
 (setq x2 (cons 'z (cdr x1)))
      @result{} (z b c)
@@ -1017,7 +1023,7 @@ reached via the @sc{cdr}.
 
 @example
 @group
-(setq x '(1 2 3))
+(setq x (list 1 2 3))
      @result{} (1 2 3)
 @end group
 @group
@@ -1037,7 +1043,7 @@ the @sc{cdr} of the first cons cell:
 
 @example
 @group
-(setq x1 '(a b c))
+(setq x1 (list 'a 'b 'c))
      @result{} (a b c)
 (setcdr x1 (cdr (cdr x1)))
      @result{} (c)
@@ -1069,7 +1075,7 @@ of this list.
 
 @example
 @group
-(setq x1 '(a b c))
+(setq x1 (list 'a 'b 'c))
      @result{} (a b c)
 (setcdr x1 (cons 'd (cdr x1)))
      @result{} (d b c)
@@ -1130,7 +1136,7 @@ Unlike @code{append} (@pxref{Building Lists}), the @var{lists} are
 
 @example
 @group
-(setq x '(1 2 3))
+(setq x (list 1 2 3))
      @result{} (1 2 3)
 @end group
 @group
@@ -1150,7 +1156,7 @@ list:
 
 @example
 @group
-(setq x '(1 2 3))
+(setq x (list 1 2 3))
      @result{} (1 2 3)
 @end group
 @group
@@ -1163,11 +1169,13 @@ x
 @end group
 @end example
 
-However, the other arguments (all but the last) must be lists.
+However, the other arguments (all but the last) must be mutable lists.
 
 A common pitfall is to use a quoted constant list as a non-last
-argument to @code{nconc}.  If you do this, your program will change
-each time you run it!  Here is what happens:
+argument to @code{nconc}.  If you do this, the resulting behavior
+is undefined.  It is possible that your program will change
+each time you run it!  Here is what might happen (though this
+is not guaranteed to happen):
 
 @smallexample
 @group
@@ -1260,7 +1268,9 @@ after those elements.  For example:
 
 @example
 @group
-(delq 'a '(a b c)) @equiv{} (cdr '(a b c))
+(equal
+ (delq 'a (list 'a 'b 'c))
+ (cdr (list 'a 'b 'c)))
 @end group
 @end example
 
@@ -1270,7 +1280,7 @@ removing it involves changing the @sc{cdr}s (@pxref{Setcdr}).
 
 @example
 @group
-(setq sample-list '(a b c (4)))
+(setq sample-list (list 'a 'b 'c '(4)))
      @result{} (a b c (4))
 @end group
 @group
@@ -1303,12 +1313,12 @@ into the variable that held the original list:
 (setq flowers (delq 'rose flowers))
 @end example
 
-In the following example, the @code{(4)} that @code{delq} attempts to match
-and the @code{(4)} in the @code{sample-list} are not @code{eq}:
+In the following example, the @code{(list 4)} that @code{delq} attempts to match
+and the @code{(4)} in the @code{sample-list} are @code{equal} but not @code{eq}:
 
 @example
 @group
-(delq '(4) sample-list)
+(delq (list 4) sample-list)
      @result{} (a c (4))
 @end group
 @end example
@@ -1324,7 +1334,7 @@ of @code{list}.
 
 @example
 @group
-(setq sample-list '(a b c a b c))
+(setq sample-list (list 'a 'b 'c 'a 'b 'c))
      @result{} (a b c a b c)
 @end group
 @group
@@ -1353,7 +1363,7 @@ Compare this with @code{memq}:
      @result{} (1.2 1.3)
 @end group
 @group
-(memq 1.2 '(1.1 1.2 1.3))  ; @r{@code{1.2} and @code{1.2} are not @code{eq}.}
+(memq (list 2) '((1) (2)))  ; @r{@code{(list 2)} and @code{(2)} are not @code{eq}.}
      @result{} nil
 @end group
 @end example
@@ -1373,11 +1383,11 @@ Compare this with @code{memq}:
 
 @example
 @group
-(member '(2) '((1) (2)))  ; @r{@code{(2)} and @code{(2)} are @code{equal}.}
+(member (list 2) '((1) (2)))  ; @r{@code{(list 2)} and @code{(2)} are @code{equal}.}
      @result{} ((2))
 @end group
 @group
-(memq '(2) '((1) (2)))    ; @r{@code{(2)} and @code{(2)} are not @code{eq}.}
+(memq (list 2) '((1) (2)))    ; @r{@code{(list 2)} and @code{(2)} are not @code{eq}.}
      @result{} nil
 @end group
 @group
@@ -1407,7 +1417,7 @@ For example:
 
 @example
 @group
-(setq l '((2) (1) (2)))
+(setq l (list '(2) '(1) '(2)))
 (delete '(2) l)
      @result{} ((1))
 l
@@ -1416,7 +1426,7 @@ l
 ;; @r{write @code{(setq l (delete '(2) l))}.}
 @end group
 @group
-(setq l '((2) (1) (2)))
+(setq l (list '(2) '(1) '(2)))
 (delete '(1) l)
      @result{} ((2) (2))
 l
@@ -1618,9 +1628,9 @@ keys may not be symbols:
       '(("simple leaves" . oak)
         ("compound leaves" . horsechestnut)))
 
-(assq "simple leaves" leaves)
+(assq (copy-sequence "simple leaves") leaves)
      @result{} nil
-(assoc "simple leaves" leaves)
+(assoc (copy-sequence "simple leaves") leaves)
      @result{} ("simple leaves" . oak)
 @end smallexample
 @end defun
@@ -1759,7 +1769,7 @@ correct results, use the return value of @code{assq-delete-all} rather
 than looking at the saved value of @var{alist}.
 
 @example
-(setq alist '((foo 1) (bar 2) (foo 3) (lose 4)))
+(setq alist (list '(foo 1) '(bar 2) '(foo 3) '(lose 4)))
      @result{} ((foo 1) (bar 2) (foo 3) (lose 4))
 (assq-delete-all 'foo alist)
      @result{} ((bar 2) (lose 4))
@@ -1926,7 +1936,7 @@ function returns the modified property list, so you can store that back
 in the place where you got @var{plist}.  For example,
 
 @example
-(setq my-plist '(bar t foo 4))
+(setq my-plist (list 'bar t 'foo 4))
      @result{} (bar t foo 4)
 (setq my-plist (plist-put my-plist 'foo 69))
      @result{} (bar t foo 69)
diff --git a/doc/lispref/sequences.texi b/doc/lispref/sequences.texi
index 1a3a04f680..f6faf9448c 100644
--- a/doc/lispref/sequences.texi
+++ b/doc/lispref/sequences.texi
@@ -183,7 +183,7 @@ for other ways to copy sequences.
 
 @example
 @group
-(setq bar '(1 2))
+(setq bar (list 1 2))
      @result{} (1 2)
 @end group
 @group
@@ -278,7 +278,7 @@ Unlike @code{reverse} the original @var{sequence} may be modified.
 
 @example
 @group
-(setq x '(a b c))
+(setq x (list 'a 'b 'c))
      @result{} (a b c)
 @end group
 @group
@@ -320,7 +320,7 @@ presented graphically:
   For the vector, it is even simpler because you don't need setq:
 
 @example
-(setq x [1 2 3 4])
+(setq x (copy-sequence [1 2 3 4]))
      @result{} [1 2 3 4]
 (nreverse x)
      @result{} [4 3 2 1]
@@ -330,7 +330,7 @@ x
 
 Note that unlike @code{reverse}, this function doesn't work with strings.
 Although you can alter string data by using @code{aset}, it is strongly
-encouraged to treat strings as immutable.
+encouraged to treat strings as immutable even when they are mutable.
 
 @end defun
 
@@ -374,11 +374,11 @@ appears in a different position in the list due to the change of
 
 @example
 @group
-(setq nums '(1 3 2 6 5 4 0))
+(setq nums (list 1 3 2 6 5 4 0))
      @result{} (1 3 2 6 5 4 0)
 @end group
 @group
-(sort nums '<)
+(sort nums #'<)
      @result{} (0 1 2 3 4 5 6)
 @end group
 @group
@@ -396,7 +396,7 @@ of @code{sort} and use that.  Most often we store the result back into
 the variable that held the original list:
 
 @example
-(setq nums (sort nums '<))
+(setq nums (sort nums #'<))
 @end example
 
 For the better understanding of what stable sort is, consider the following
@@ -1228,7 +1228,7 @@ This function sets the @var{index}th element of @var{array} to be
 
 @example
 @group
-(setq w [foo bar baz])
+(setq w (vector 'foo 'bar 'baz))
      @result{} [foo bar baz]
 (aset w 0 'fu)
      @result{} fu
@@ -1237,7 +1237,8 @@ w
 @end group
 
 @group
-(setq x "asdfasfd")
+;; @r{@code{copy-sequence} creates a mutable string.}
+(setq x (copy-sequence "asdfasfd"))
      @result{} "asdfasfd"
 (aset x 3 ?Z)
      @result{} 90
@@ -1246,6 +1247,10 @@ x
 @end group
 @end example
 
+The @var{array} should be mutable; that is, it should not be a constant,
+such as the constants created via quoting or via self-evaluating forms.
+@xref{Self-Evaluating Forms}.
+
 If @var{array} is a string and @var{object} is not a character, a
 @code{wrong-type-argument} error results.  The function converts a
 unibyte string to multibyte if necessary to insert a character.
@@ -1257,7 +1262,7 @@ each element of @var{array} is @var{object}.  It returns @var{array}.
 
 @example
 @group
-(setq a [a b c d e f g])
+(setq a (copy-sequence [a b c d e f g]))
      @result{} [a b c d e f g]
 (fillarray a 0)
      @result{} [0 0 0 0 0 0 0]
@@ -1265,7 +1270,7 @@ a
      @result{} [0 0 0 0 0 0 0]
 @end group
 @group
-(setq s "When in the course")
+(setq s (copy-sequence "When in the course"))
      @result{} "When in the course"
 (fillarray s ?-)
      @result{} "------------------"
@@ -1301,7 +1306,9 @@ same way in Lisp input.
 
   A vector, like a string or a number, is considered a constant for
 evaluation: the result of evaluating it is the same vector.  This does
-not evaluate or even examine the elements of the vector.
+not evaluate or even examine the elements of the vector.  Vectors
+written with square brackets are constants and should not be modified
+via @code{aset} or other destructive operations.
 @xref{Self-Evaluating Forms}.
 
   Here are examples illustrating these principles:
diff --git a/doc/lispref/strings.texi b/doc/lispref/strings.texi
index 14cabc5d79..3acbf538dc 100644
--- a/doc/lispref/strings.texi
+++ b/doc/lispref/strings.texi
@@ -51,10 +51,8 @@ by a distinguished character code.
 operate on them with the general array and sequence functions documented
 in @ref{Sequences Arrays Vectors}.  For example, you can access or
 change individual characters in a string using the functions @code{aref}
-and @code{aset} (@pxref{Array Functions}).  However, note that
-@code{length} should @emph{not} be used for computing the width of a
-string on display; use @code{string-width} (@pxref{Size of Displayed
-Text}) instead.
+and @code{aset} (@pxref{Array Functions}).  However, you should not
+try to change the contents of constant strings (@pxref{Modifying Strings}).
 
   There are two text representations for non-@acronym{ASCII}
 characters in Emacs strings (and in buffers): unibyte and multibyte.
@@ -89,6 +87,9 @@ copy them into buffers.  @xref{Character Type}, and @ref{String Type},
 for information about the syntax of characters and strings.
 @xref{Non-ASCII Characters}, for functions to convert between text
 representations and to encode and decode character codes.
+Also, note that @code{length} should @emph{not} be used for computing
+the width of a string on display; use @code{string-width} (@pxref{Size
+of Displayed Text}) instead.
 
 @node Predicates for Strings
 @section Predicates for Strings
@@ -380,6 +381,10 @@ usual value is @w{@code{"[ \f\t\n\r\v]+"}}.
 @cindex modifying strings
 @cindex string modification
 
+  You can alter the contents of a mutable string via operations
+described in this section.  However, you should not try to use these
+operations to alter the contents of a constant string.
+
   The most basic way to alter the contents of an existing string is with
 @code{aset} (@pxref{Array Functions}).  @code{(aset @var{string}
 @var{idx} @var{char})} stores @var{char} into @var{string} at index
@@ -591,7 +596,7 @@ for sorting (@pxref{Sequence Functions}):
 
 @example
 @group
-(sort '("11" "12" "1 1" "1 2" "1.1" "1.2") 'string-collate-lessp)
+(sort (list "11" "12" "1 1" "1 2" "1.1" "1.2") 'string-collate-lessp)
      @result{} ("11" "1 1" "1.1" "12" "1 2" "1.2")
 @end group
 @end example
@@ -608,7 +613,7 @@ systems.  The @var{locale} value of @code{"POSIX"} or @code{"C"} lets
 
 @example
 @group
-(sort '("11" "12" "1 1" "1 2" "1.1" "1.2")
+(sort (list "11" "12" "1 1" "1 2" "1.1" "1.2")
       (lambda (s1 s2) (string-collate-lessp s1 s2 "POSIX")))
      @result{} ("1 1" "1 2" "1.1" "1.2" "11" "12")
 @end group
-- 
2.17.1