From eebfb72c906755c0a80d92c11deee7ac9faf5f4b Mon Sep 17 00:00:00 2001 From: Paul Eggert 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=utf8 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 bd688070a3a..630676d9786 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 8be8307c75f..ec76e83db1c 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 c6a02d721f0..4db9969767c 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 27fa5385e35..c2771b01652 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 1a3a04f680b..f6faf9448c2 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 14cabc5d79d..3acbf538dce 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.39.2