mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-11-26 07:33:47 +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:
parent
b4937f64cd
commit
6ac2326e5b
@ -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.
|
||||
|
||||
@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} special form. Because we intend to use
|
||||
@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
|
||||
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:
|
||||
animal list by using the @code{list} function, as follows:
|
||||
|
||||
@smallexample
|
||||
(setq animals (list 'antelope 'giraffe 'lion 'tiger))
|
||||
|
@ -297,7 +297,7 @@ Lisp Data Types
|
||||
* Circular Objects:: Read syntax for circular structure.
|
||||
* Type Predicates:: Tests related to types.
|
||||
* 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
|
||||
|
||||
|
@ -158,11 +158,11 @@ contents unchanged.
|
||||
@end group
|
||||
@end example
|
||||
|
||||
A self-evaluating form yields constant conses, vectors and strings, and you
|
||||
should not attempt to modify their contents via @code{setcar}, @code{aset} or
|
||||
A self-evaluating form yields a value that becomes part of the program,
|
||||
and you should not try to modify it via @code{setcar}, @code{aset} or
|
||||
similar operations. The Lisp interpreter might unify the constants
|
||||
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
|
||||
in Lisp code, taking advantage of the fact that they self-evaluate.
|
||||
@ -564,8 +564,8 @@ and vectors.)
|
||||
|
||||
@defspec quote object
|
||||
This special form returns @var{object}, without evaluating it.
|
||||
The returned value is a constant, and should not be modified.
|
||||
@xref{Constants and Mutability}.
|
||||
The returned value might be shared and should not be modified.
|
||||
@xref{Self-Evaluating Forms}.
|
||||
@end defspec
|
||||
|
||||
@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)}
|
||||
both yield lists equal to @code{(+ 1 2)}, the former yields a
|
||||
freshly-minted mutable list whereas the latter yields a constant list
|
||||
built from conses that may be shared with other constants.
|
||||
@xref{Constants and Mutability}.
|
||||
freshly-minted mutable list whereas the latter yields a list
|
||||
built from conses that might be shared and should not be modified.
|
||||
@xref{Self-Evaluating Forms}.
|
||||
|
||||
Other quoting constructs include @code{function} (@pxref{Anonymous
|
||||
Functions}), which causes an anonymous lambda expression written in Lisp
|
||||
@ -710,8 +710,9 @@ Here are some examples:
|
||||
@end example
|
||||
|
||||
If a subexpression of a backquote construct has no substitutions or
|
||||
splices, it acts like @code{quote} in that it yields constant conses,
|
||||
vectors and strings that should not be modified.
|
||||
splices, it acts like @code{quote} in that it yields conses,
|
||||
vectors and strings that might be shared and should not be modified.
|
||||
@xref{Self-Evaluating Forms}.
|
||||
|
||||
@node Eval
|
||||
@section Eval
|
||||
|
@ -873,8 +873,8 @@ primitives @code{setcar} and @code{setcdr}. These are destructive
|
||||
operations because they change existing list structure.
|
||||
Destructive operations should be applied only to 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. @xref{Constants and Mutability}.
|
||||
operations. Lists created by quoting are part of the program and
|
||||
should not be changed by destructive operations. @xref{Mutability}.
|
||||
|
||||
@cindex CL note---@code{rplaca} vs @code{setcar}
|
||||
@quotation
|
||||
@ -911,7 +911,7 @@ value @var{object}. For example:
|
||||
|
||||
@example
|
||||
@group
|
||||
(setq x (list 1 2)) ; @r{Create a mutable list.}
|
||||
(setq x (list 1 2))
|
||||
@result{} (1 2)
|
||||
@end group
|
||||
@group
|
||||
@ -931,7 +931,7 @@ these lists. Here is an example:
|
||||
|
||||
@example
|
||||
@group
|
||||
;; @r{Create two mutable lists that are partly shared.}
|
||||
;; @r{Create two lists that are partly shared.}
|
||||
(setq x1 (list 'a 'b 'c))
|
||||
@result{} (a b c)
|
||||
(setq x2 (cons 'z (cdr x1)))
|
||||
@ -1022,11 +1022,11 @@ reached via the @sc{cdr}.
|
||||
|
||||
@example
|
||||
@group
|
||||
(setq x (list 1 2 3)) ; @r{Create a mutable list.}
|
||||
(setq x (list 1 2 3))
|
||||
@result{} (1 2 3)
|
||||
@end group
|
||||
@group
|
||||
(setcdr x '(4)) ; @r{Modify the list's tail to be a constant list.}
|
||||
(setcdr x '(4))
|
||||
@result{} (4)
|
||||
@end group
|
||||
@group
|
||||
@ -1135,11 +1135,11 @@ Unlike @code{append} (@pxref{Building Lists}), the @var{lists} are
|
||||
|
||||
@example
|
||||
@group
|
||||
(setq x (list 1 2 3)) ; @r{Create a mutable list.}
|
||||
(setq x (list 1 2 3))
|
||||
@result{} (1 2 3)
|
||||
@end 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)
|
||||
@end group
|
||||
@group
|
||||
|
@ -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.
|
||||
@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
|
||||
syntax of each of the standard types in GNU Emacs Lisp. Details on how
|
||||
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.
|
||||
* Type Predicates:: Tests related to types.
|
||||
* 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
|
||||
|
||||
@node Printed Representation
|
||||
@ -2379,51 +2375,59 @@ that for two strings to be equal, they have the same text properties.
|
||||
@end example
|
||||
@end defun
|
||||
|
||||
@node Constants and Mutability
|
||||
@section Constants and Mutability
|
||||
@cindex constants
|
||||
@node Mutability
|
||||
@section Mutability
|
||||
@cindex mutable objects
|
||||
|
||||
Some Lisp objects are constant: their values should never change
|
||||
during a single execution of Emacs running well-behaved Lisp code.
|
||||
For example, you can create a new integer by calculating one, but you
|
||||
cannot modify the value of an existing integer.
|
||||
Some Lisp objects should never change. For example, the Lisp
|
||||
expression @code{"aaa"} yields a string, but you should not change
|
||||
its contents. Indeed, some objects cannot be changed; for example,
|
||||
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
|
||||
via destructive operations involving side effects. For example, an
|
||||
existing marker can be changed by moving the marker to point to
|
||||
somewhere else.
|
||||
Other Lisp objects are @dfn{mutable}: it is safe to change their
|
||||
values via destructive operations involving side effects. For
|
||||
example, an existing marker can be changed by moving the marker to
|
||||
point to somewhere else.
|
||||
|
||||
Although all numbers are constants and all markers are
|
||||
mutable, some types contain both constant and mutable members. These
|
||||
types include conses, vectors, strings, and symbols. For example, the string
|
||||
literal @code{"aaa"} yields a constant string, whereas the function
|
||||
call @code{(make-string 3 ?a)} yields a mutable string that can be
|
||||
changed via later calls to @code{aset}.
|
||||
Although numbers never change and all markers are mutable,
|
||||
some types have members some of which are mutable and others not. These
|
||||
types include conses, vectors, and strings. For example,
|
||||
although @code{"aaa"} yields a string that should not be changed,
|
||||
@code{(make-string 3 ?a)} yields a mutable string that can be
|
||||
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
|
||||
that is evaluated. The reverse does not occur: constant objects
|
||||
should stay constant.
|
||||
A mutable object stops being mutable if it is part of an expression
|
||||
that is evaluated. For example:
|
||||
|
||||
Trying to modify a constant variable signals an error
|
||||
(@pxref{Constant Variables}).
|
||||
A program should not attempt to modify other types of constants because the
|
||||
resulting behavior is undefined: the Lisp interpreter might or might
|
||||
not detect the error, and if it does not detect the error the
|
||||
interpreter can behave unpredictably thereafter. Another way to put
|
||||
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.
|
||||
@example
|
||||
(let* ((x (list 0.5))
|
||||
(y (eval (list 'quote x))))
|
||||
(setcar x 1.5) ;; The program should not do this.
|
||||
y)
|
||||
@end example
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
regardless of whether this optimization is in use.
|
||||
|
@ -183,11 +183,11 @@ for other ways to copy sequences.
|
||||
|
||||
@example
|
||||
@group
|
||||
(setq bar (list 1 2)) ; @r{Create a mutable list.}
|
||||
(setq bar (list 1 2))
|
||||
@result{} (1 2)
|
||||
@end group
|
||||
@group
|
||||
(setq x (vector 'foo bar)) ; @r{Create a mutable vector.}
|
||||
(setq x (vector 'foo bar))
|
||||
@result{} [foo (1 2)]
|
||||
@end group
|
||||
@group
|
||||
@ -278,7 +278,7 @@ Unlike @code{reverse} the original @var{sequence} may be modified.
|
||||
|
||||
@example
|
||||
@group
|
||||
(setq x (list 'a 'b 'c)) ; @r{Create a mutable list.}
|
||||
(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 (copy-sequence [1 2 3 4])) ; @r{Create a mutable vector.}
|
||||
(setq x (copy-sequence [1 2 3 4]))
|
||||
@result{} [1 2 3 4]
|
||||
(nreverse x)
|
||||
@result{} [4 3 2 1]
|
||||
@ -331,6 +331,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 even when they are mutable.
|
||||
@xref{Mutability}.
|
||||
|
||||
@end defun
|
||||
|
||||
@ -374,7 +375,7 @@ appears in a different position in the list due to the change of
|
||||
|
||||
@example
|
||||
@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)
|
||||
@end group
|
||||
@group
|
||||
@ -1228,7 +1229,7 @@ This function sets the @var{index}th element of @var{array} to be
|
||||
|
||||
@example
|
||||
@group
|
||||
(setq w (vector 'foo 'bar 'baz)) ; @r{Create a mutable vector.}
|
||||
(setq w (vector 'foo 'bar 'baz))
|
||||
@result{} [foo bar baz]
|
||||
(aset w 0 'fu)
|
||||
@result{} fu
|
||||
@ -1237,7 +1238,7 @@ w
|
||||
@end 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"))
|
||||
@result{} "asdfasfd"
|
||||
(aset x 3 ?Z)
|
||||
@ -1247,9 +1248,7 @@ 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{Constants and Mutability}.
|
||||
The @var{array} should be mutable. @xref{Mutability}.
|
||||
|
||||
If @var{array} is a string and @var{object} is not a character, 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
|
||||
@group
|
||||
;; @r{Create a mutable vector and then fill it with zeros.}
|
||||
(setq a (copy-sequence [a b c d e f g]))
|
||||
@result{} [a b c d e f g]
|
||||
(fillarray a 0)
|
||||
@ -1271,7 +1269,6 @@ a
|
||||
@result{} [0 0 0 0 0 0 0]
|
||||
@end group
|
||||
@group
|
||||
;; @r{Create a mutable string and then fill it with "-".}
|
||||
(setq s (copy-sequence "When in the course"))
|
||||
@result{} "When in the course"
|
||||
(fillarray s ?-)
|
||||
@ -1310,8 +1307,8 @@ same way in Lisp input.
|
||||
evaluation: the result of evaluating it is the same vector. This does
|
||||
not evaluate or even examine the elements of the vector.
|
||||
@xref{Self-Evaluating Forms}. Vectors written with square brackets
|
||||
are constants and should not be modified via @code{aset} or other
|
||||
destructive operations. @xref{Constants and Mutability}.
|
||||
should not be modified via @code{aset} or other destructive
|
||||
operations. @xref{Mutability}.
|
||||
|
||||
Here are examples illustrating these principles:
|
||||
|
||||
|
@ -49,10 +49,9 @@ by a distinguished character code.
|
||||
|
||||
Since strings are arrays, and therefore sequences as well, you can
|
||||
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, you should not
|
||||
try to change the contents of constant strings (@pxref{Modifying Strings}).
|
||||
in @ref{Sequences Arrays Vectors}. For example, you can access
|
||||
individual characters in a string using the function @code{aref}
|
||||
(@pxref{Array Functions}).
|
||||
|
||||
There are two text representations for non-@acronym{ASCII}
|
||||
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
|
||||
|
||||
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.
|
||||
@xref{Constants and Mutability}.
|
||||
described in this section. @xref{Mutability}.
|
||||
|
||||
The most basic way to alter the contents of an existing string is with
|
||||
@code{aset} (@pxref{Array Functions}). @code{(aset @var{string}
|
||||
|
Loading…
Reference in New Issue
Block a user