[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
emacs-27 eebfb72 1/2: Document constant vs mutable objects better
From: |
Paul Eggert |
Subject: |
emacs-27 eebfb72 1/2: Document constant vs mutable objects better |
Date: |
Sat, 18 Apr 2020 16:01:14 -0400 (EDT) |
branch: emacs-27
commit eebfb72c906755c0a80d92c11deee7ac9faf5f4b
Author: Paul Eggert <address@hidden>
Commit: Paul Eggert <address@hidden>
Document constant vs mutable objects better
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 bd68807..630676d 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 8be8307..ec76e83 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 c6a02d7..4db9969 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 27fa538..c2771b0 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 1a3a04f..f6faf94 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 14cabc5..3acbf53 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