1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-11-27 07:37:33 +00:00

Don’t use “constant” for values you shouldn’t change

Inspired by patch proposed by Dmitry Gutov (Bug#40671#393)
and by further comments by him and by Michael Heerdegen
in the same bug report.
* doc/lispintro/emacs-lisp-intro.texi (setcar):
Don’t push mutability here.
* doc/lispref/eval.texi (Self-Evaluating Forms, Quoting)
(Backquote):
* doc/lispref/lists.texi (Modifying Lists):
* doc/lispref/objects.texi (Lisp Data Types, Mutability):
* doc/lispref/sequences.texi (Array Functions, Vectors):
* doc/lispref/strings.texi (String Basics, Modifying Strings):
Don’t use the word “constant” to describe all values that
a program should not change.
* doc/lispref/objects.texi (Mutability):
Rename from “Constants and Mutability”.  All uses changed.
In a footnote, contrast the Emacs behavior with that of Common
Lisp, Python, etc. for clarity, and say the goal is to be nicer.
This commit is contained in:
Paul Eggert 2020-05-16 17:17:00 -07:00
parent b4937f64cd
commit 6ac2326e5b
7 changed files with 82 additions and 86 deletions

View File

@ -7317,8 +7317,6 @@ 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. works is to experiment. We will start with the @code{setcar} function.
@need 1200 @need 1200
@cindex constant lists
@cindex mutable lists
First, we can make a list and then set the value of a variable to the First, we can make a list and then set the value of a variable to the
list, using the @code{setq} special form. Because we intend to use 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 @code{setcar} to change the list, this @code{setq} should not use the
@ -7327,8 +7325,7 @@ 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 tried to change part of the program while running it. Generally
speaking an Emacs Lisp program's components should be constant (or speaking an Emacs Lisp program's components should be constant (or
unchanged) while the program is running. So we instead construct an unchanged) while the program is running. So we instead construct an
animal list that is @dfn{mutable} (or changeable) by using the animal list by using the @code{list} function, as follows:
@code{list} function, as follows:
@smallexample @smallexample
(setq animals (list 'antelope 'giraffe 'lion 'tiger)) (setq animals (list 'antelope 'giraffe 'lion 'tiger))

View File

@ -297,7 +297,7 @@ Lisp Data Types
* Circular Objects:: Read syntax for circular structure. * Circular Objects:: Read syntax for circular structure.
* Type Predicates:: Tests related to types. * Type Predicates:: Tests related to types.
* Equality Predicates:: Tests of equality between any two objects. * Equality Predicates:: Tests of equality between any two objects.
* Constants and Mutability:: Whether an object's value can change. * Mutability:: Some objects should not be modified.
Programming Types Programming Types

View File

@ -158,11 +158,11 @@ contents unchanged.
@end group @end group
@end example @end example
A self-evaluating form yields constant conses, vectors and strings, and you A self-evaluating form yields a value that becomes part of the program,
should not attempt to modify their contents via @code{setcar}, @code{aset} or and you should not try to modify it via @code{setcar}, @code{aset} or
similar operations. The Lisp interpreter might unify the constants similar operations. The Lisp interpreter might unify the constants
yielded by your program's self-evaluating forms, so that these yielded by your program's self-evaluating forms, so that these
constants might share structure. @xref{Constants and Mutability}. constants might share structure. @xref{Mutability}.
It is common to write numbers, characters, strings, and even vectors It is common to write numbers, characters, strings, and even vectors
in Lisp code, taking advantage of the fact that they self-evaluate. in Lisp code, taking advantage of the fact that they self-evaluate.
@ -564,8 +564,8 @@ and vectors.)
@defspec quote object @defspec quote object
This special form returns @var{object}, without evaluating it. This special form returns @var{object}, without evaluating it.
The returned value is a constant, and should not be modified. The returned value might be shared and should not be modified.
@xref{Constants and Mutability}. @xref{Self-Evaluating Forms}.
@end defspec @end defspec
@cindex @samp{'} for quoting @cindex @samp{'} for quoting
@ -608,9 +608,9 @@ Here are some examples of expressions that use @code{quote}:
Although the expressions @code{(list '+ 1 2)} and @code{'(+ 1 2)} Although the expressions @code{(list '+ 1 2)} and @code{'(+ 1 2)}
both yield lists equal to @code{(+ 1 2)}, the former yields a both yield lists equal to @code{(+ 1 2)}, the former yields a
freshly-minted mutable list whereas the latter yields a constant list freshly-minted mutable list whereas the latter yields a list
built from conses that may be shared with other constants. built from conses that might be shared and should not be modified.
@xref{Constants and Mutability}. @xref{Self-Evaluating Forms}.
Other quoting constructs include @code{function} (@pxref{Anonymous Other quoting constructs include @code{function} (@pxref{Anonymous
Functions}), which causes an anonymous lambda expression written in Lisp Functions}), which causes an anonymous lambda expression written in Lisp
@ -710,8 +710,9 @@ Here are some examples:
@end example @end example
If a subexpression of a backquote construct has no substitutions or If a subexpression of a backquote construct has no substitutions or
splices, it acts like @code{quote} in that it yields constant conses, splices, it acts like @code{quote} in that it yields conses,
vectors and strings that should not be modified. vectors and strings that might be shared and should not be modified.
@xref{Self-Evaluating Forms}.
@node Eval @node Eval
@section Eval @section Eval

View File

@ -873,8 +873,8 @@ primitives @code{setcar} and @code{setcdr}. These are destructive
operations because they change existing list structure. operations because they change existing list structure.
Destructive operations should be applied only to mutable lists, Destructive operations should be applied only to mutable lists,
that is, lists constructed via @code{cons}, @code{list} or similar that is, lists constructed via @code{cons}, @code{list} or similar
operations. Lists created by quoting are constants and should not be operations. Lists created by quoting are part of the program and
changed by destructive operations. @xref{Constants and Mutability}. should not be changed by destructive operations. @xref{Mutability}.
@cindex CL note---@code{rplaca} vs @code{setcar} @cindex CL note---@code{rplaca} vs @code{setcar}
@quotation @quotation
@ -911,7 +911,7 @@ value @var{object}. For example:
@example @example
@group @group
(setq x (list 1 2)) ; @r{Create a mutable list.} (setq x (list 1 2))
@result{} (1 2) @result{} (1 2)
@end group @end group
@group @group
@ -931,7 +931,7 @@ these lists. Here is an example:
@example @example
@group @group
;; @r{Create two mutable lists that are partly shared.} ;; @r{Create two lists that are partly shared.}
(setq x1 (list 'a 'b 'c)) (setq x1 (list 'a 'b 'c))
@result{} (a b c) @result{} (a b c)
(setq x2 (cons 'z (cdr x1))) (setq x2 (cons 'z (cdr x1)))
@ -1022,11 +1022,11 @@ reached via the @sc{cdr}.
@example @example
@group @group
(setq x (list 1 2 3)) ; @r{Create a mutable list.} (setq x (list 1 2 3))
@result{} (1 2 3) @result{} (1 2 3)
@end group @end group
@group @group
(setcdr x '(4)) ; @r{Modify the list's tail to be a constant list.} (setcdr x '(4))
@result{} (4) @result{} (4)
@end group @end group
@group @group
@ -1135,11 +1135,11 @@ Unlike @code{append} (@pxref{Building Lists}), the @var{lists} are
@example @example
@group @group
(setq x (list 1 2 3)) ; @r{Create a mutable list.} (setq x (list 1 2 3))
@result{} (1 2 3) @result{} (1 2 3)
@end group @end group
@group @group
(nconc x '(4 5)) ; @r{Modify the list's tail to be a constant list.} (nconc x '(4 5))
@result{} (1 2 3 4 5) @result{} (1 2 3 4 5)
@end group @end group
@group @group

View File

@ -46,10 +46,6 @@ you store in it, type and all. (Actually, a small number of Emacs
Lisp variables can only take on values of a certain type. Lisp variables can only take on values of a certain type.
@xref{Variables with Restricted Values}.) @xref{Variables with Restricted Values}.)
Some Lisp objects are @dfn{constant}: their values should never change.
Others are @dfn{mutable}: their values can be changed via destructive
operations that involve side effects.
This chapter describes the purpose, printed representation, and read This chapter describes the purpose, printed representation, and read
syntax of each of the standard types in GNU Emacs Lisp. Details on how syntax of each of the standard types in GNU Emacs Lisp. Details on how
to use these types can be found in later chapters. to use these types can be found in later chapters.
@ -63,7 +59,7 @@ to use these types can be found in later chapters.
* Circular Objects:: Read syntax for circular structure. * Circular Objects:: Read syntax for circular structure.
* Type Predicates:: Tests related to types. * Type Predicates:: Tests related to types.
* Equality Predicates:: Tests of equality between any two objects. * Equality Predicates:: Tests of equality between any two objects.
* Constants and Mutability:: Whether an object's value can change. * Mutability:: Some objects should not be modified.
@end menu @end menu
@node Printed Representation @node Printed Representation
@ -2379,51 +2375,59 @@ that for two strings to be equal, they have the same text properties.
@end example @end example
@end defun @end defun
@node Constants and Mutability @node Mutability
@section Constants and Mutability @section Mutability
@cindex constants
@cindex mutable objects @cindex mutable objects
Some Lisp objects are constant: their values should never change Some Lisp objects should never change. For example, the Lisp
during a single execution of Emacs running well-behaved Lisp code. expression @code{"aaa"} yields a string, but you should not change
For example, you can create a new integer by calculating one, but you its contents. Indeed, some objects cannot be changed; for example,
cannot modify the value of an existing integer. although you can create a new number by calculating one, Lisp provides
no operation to change the value of an existing number.
Other Lisp objects are mutable: it is safe to change their values Other Lisp objects are @dfn{mutable}: it is safe to change their
via destructive operations involving side effects. For example, an values via destructive operations involving side effects. For
existing marker can be changed by moving the marker to point to example, an existing marker can be changed by moving the marker to
somewhere else. point to somewhere else.
Although all numbers are constants and all markers are Although numbers never change and all markers are mutable,
mutable, some types contain both constant and mutable members. These some types have members some of which are mutable and others not. These
types include conses, vectors, strings, and symbols. For example, the string types include conses, vectors, and strings. For example,
literal @code{"aaa"} yields a constant string, whereas the function although @code{"aaa"} yields a string that should not be changed,
call @code{(make-string 3 ?a)} yields a mutable string that can be @code{(make-string 3 ?a)} yields a mutable string that can be
changed via later calls to @code{aset}. changed via later calls to @code{aset}. Another example:
@code{(symbol-name 'cons)} yields a string @code{"cons"} that should
not be changed.
A mutable object can become constant if it is part of an expression A mutable object stops being mutable if it is part of an expression
that is evaluated. The reverse does not occur: constant objects that is evaluated. For example:
should stay constant.
Trying to modify a constant variable signals an error @example
(@pxref{Constant Variables}). (let* ((x (list 0.5))
A program should not attempt to modify other types of constants because the (y (eval (list 'quote x))))
resulting behavior is undefined: the Lisp interpreter might or might (setcar x 1.5) ;; The program should not do this.
not detect the error, and if it does not detect the error the y)
interpreter can behave unpredictably thereafter. Another way to put @end example
this is that although mutable objects are safe to change and constant
variables reliably prevent attempts to change them, other constants
are not safely mutable: if a misbehaving program tries to change such a
constant then the constant's value might actually change, or the
program might crash or worse. This problem occurs
with types that have both constant and mutable members, and that have
mutators like @code{setcar} and @code{aset} that are valid on mutable
objects but hazardous on constants.
When the same constant occurs multiple times in a program, the Lisp @noindent
Although the list @code{(0.5)} was mutable when it was created, it should not
have been changed via @code{setcar} because it given to @code{eval}. The
reverse does not occur: an object that should not be changed never
becomes mutable afterwards.
If a program attempts to change objects that should not be
changed, the resulting behavior is undefined: the Lisp interpreter
might signal an error, or it might crash or behave unpredictably in
other ways.@footnote{This is the behavior specified for languages like
Common Lisp and C, and it differs from the behavior of languages like
JavaScript and Python where an interpreter is required to signal an
error if a program attempts to change a constant. Ideally the Emacs
Lisp interpreter will evolve in latter direction.}
When similar constants occur as parts of a program, the Lisp
interpreter might save time or space by reusing existing constants or interpreter might save time or space by reusing existing constants or
constant components. For example, @code{(eq "abc" "abc")} returns their components. For example, @code{(eq "abc" "abc")} returns
@code{t} if the interpreter creates only one instance of the string @code{t} if the interpreter creates only one instance of the string
constant @code{"abc"}, and returns @code{nil} if it creates two literal @code{"abc"}, and returns @code{nil} if it creates two
instances. Lisp programs should be written so that they work instances. Lisp programs should be written so that they work
regardless of whether this optimization is in use. regardless of whether this optimization is in use.

View File

@ -183,11 +183,11 @@ for other ways to copy sequences.
@example @example
@group @group
(setq bar (list 1 2)) ; @r{Create a mutable list.} (setq bar (list 1 2))
@result{} (1 2) @result{} (1 2)
@end group @end group
@group @group
(setq x (vector 'foo bar)) ; @r{Create a mutable vector.} (setq x (vector 'foo bar))
@result{} [foo (1 2)] @result{} [foo (1 2)]
@end group @end group
@group @group
@ -278,7 +278,7 @@ Unlike @code{reverse} the original @var{sequence} may be modified.
@example @example
@group @group
(setq x (list 'a 'b 'c)) ; @r{Create a mutable list.} (setq x (list 'a 'b 'c))
@result{} (a b c) @result{} (a b c)
@end group @end group
@group @group
@ -320,7 +320,7 @@ presented graphically:
For the vector, it is even simpler because you don't need setq: For the vector, it is even simpler because you don't need setq:
@example @example
(setq x (copy-sequence [1 2 3 4])) ; @r{Create a mutable vector.} (setq x (copy-sequence [1 2 3 4]))
@result{} [1 2 3 4] @result{} [1 2 3 4]
(nreverse x) (nreverse x)
@result{} [4 3 2 1] @result{} [4 3 2 1]
@ -331,6 +331,7 @@ x
Note that unlike @code{reverse}, this function doesn't work with strings. 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 Although you can alter string data by using @code{aset}, it is strongly
encouraged to treat strings as immutable even when they are mutable. encouraged to treat strings as immutable even when they are mutable.
@xref{Mutability}.
@end defun @end defun
@ -374,7 +375,7 @@ appears in a different position in the list due to the change of
@example @example
@group @group
(setq nums (list 1 3 2 6 5 4 0)) ; @r{Create a mutable list.} (setq nums (list 1 3 2 6 5 4 0))
@result{} (1 3 2 6 5 4 0) @result{} (1 3 2 6 5 4 0)
@end group @end group
@group @group
@ -1228,7 +1229,7 @@ This function sets the @var{index}th element of @var{array} to be
@example @example
@group @group
(setq w (vector 'foo 'bar 'baz)) ; @r{Create a mutable vector.} (setq w (vector 'foo 'bar 'baz))
@result{} [foo bar baz] @result{} [foo bar baz]
(aset w 0 'fu) (aset w 0 'fu)
@result{} fu @result{} fu
@ -1237,7 +1238,7 @@ w
@end group @end group
@group @group
;; @r{@code{copy-sequence} creates a mutable string.} ;; @r{@code{copy-sequence} copies the string to be modified later.}
(setq x (copy-sequence "asdfasfd")) (setq x (copy-sequence "asdfasfd"))
@result{} "asdfasfd" @result{} "asdfasfd"
(aset x 3 ?Z) (aset x 3 ?Z)
@ -1247,9 +1248,7 @@ x
@end group @end group
@end example @end example
The @var{array} should be mutable; that is, it should not be a constant, The @var{array} should be mutable. @xref{Mutability}.
such as the constants created via quoting or via self-evaluating forms.
@xref{Constants and Mutability}.
If @var{array} is a string and @var{object} is not a character, a If @var{array} is a string and @var{object} is not a character, a
@code{wrong-type-argument} error results. The function converts a @code{wrong-type-argument} error results. The function converts a
@ -1262,7 +1261,6 @@ each element of @var{array} is @var{object}. It returns @var{array}.
@example @example
@group @group
;; @r{Create a mutable vector and then fill it with zeros.}
(setq a (copy-sequence [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] @result{} [a b c d e f g]
(fillarray a 0) (fillarray a 0)
@ -1271,7 +1269,6 @@ a
@result{} [0 0 0 0 0 0 0] @result{} [0 0 0 0 0 0 0]
@end group @end group
@group @group
;; @r{Create a mutable string and then fill it with "-".}
(setq s (copy-sequence "When in the course")) (setq s (copy-sequence "When in the course"))
@result{} "When in the course" @result{} "When in the course"
(fillarray s ?-) (fillarray s ?-)
@ -1310,8 +1307,8 @@ same way in Lisp input.
evaluation: the result of evaluating it is the same vector. This does 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.
@xref{Self-Evaluating Forms}. Vectors written with square brackets @xref{Self-Evaluating Forms}. Vectors written with square brackets
are constants and should not be modified via @code{aset} or other should not be modified via @code{aset} or other destructive
destructive operations. @xref{Constants and Mutability}. operations. @xref{Mutability}.
Here are examples illustrating these principles: Here are examples illustrating these principles:

View File

@ -49,10 +49,9 @@ by a distinguished character code.
Since strings are arrays, and therefore sequences as well, you can Since strings are arrays, and therefore sequences as well, you can
operate on them with the general array and sequence functions documented operate on them with the general array and sequence functions documented
in @ref{Sequences Arrays Vectors}. For example, you can access or in @ref{Sequences Arrays Vectors}. For example, you can access
change individual characters in a string using the functions @code{aref} individual characters in a string using the function @code{aref}
and @code{aset} (@pxref{Array Functions}). However, you should not (@pxref{Array Functions}).
try to change the contents of constant strings (@pxref{Modifying Strings}).
There are two text representations for non-@acronym{ASCII} There are two text representations for non-@acronym{ASCII}
characters in Emacs strings (and in buffers): unibyte and multibyte. characters in Emacs strings (and in buffers): unibyte and multibyte.
@ -382,9 +381,7 @@ usual value is @w{@code{"[ \f\t\n\r\v]+"}}.
@cindex string modification @cindex string modification
You can alter the contents of a mutable string via operations You can alter the contents of a mutable string via operations
described in this section. However, you should not try to use these described in this section. @xref{Mutability}.
operations to alter the contents of a constant string.
@xref{Constants and Mutability}.
The most basic way to alter the contents of an existing string is with The most basic way to alter the contents of an existing string is with
@code{aset} (@pxref{Array Functions}). @code{(aset @var{string} @code{aset} (@pxref{Array Functions}). @code{(aset @var{string}