* bug#40671: [DOC] modify literal objects
@ 2020-04-16 19:28 Kevin Vigouroux via Bug reports for GNU Emacs, the Swiss army knife of text editors
2020-04-17 16:09 ` Mattias Engdegård
2020-04-18 20:10 ` Paul Eggert
0 siblings, 2 replies; 170+ messages in thread
From: Kevin Vigouroux via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2020-04-16 19:28 UTC (permalink / raw)
To: 40671
Hello!
The Emacs Lisp manual often gives the impression that the user can
modify literal lists (e.g. 5.6.1 Altering List Elements with `setcar`).
LISP> (setq x '(1 2))
(1 2)
LISP> (setcar x 4)
LISP> x
(4 2)
However, it is also mentioned that one should not modify the literal
objects because of the byte compilation (c.f. 2.7 Equality Predicate).
Can we modify literal objects?
See Also:
https://emacs.stackexchange.com/questions/45820/when-to-use-quote-for-lists-modifying-quoted-lists-in-elisp
https://emacs.stackexchange.com/questions/57806/which-lisp-objects-are-byte-compiled
Best regards,
Kevin Vigouroux.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-16 19:28 bug#40671: [DOC] modify literal objects Kevin Vigouroux via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2020-04-17 16:09 ` Mattias Engdegård
2020-04-17 16:37 ` Mattias Engdegård
2020-04-18 20:10 ` Paul Eggert
1 sibling, 1 reply; 170+ messages in thread
From: Mattias Engdegård @ 2020-04-17 16:09 UTC (permalink / raw)
To: 40671; +Cc: Kevin Vigouroux
>Can we modify literal objects?
No, and the manual should do a much better job at explaining this. At the very least it should not promulgate
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-17 16:09 ` Mattias Engdegård
@ 2020-04-17 16:37 ` Mattias Engdegård
2020-04-17 17:27 ` Eli Zaretskii
0 siblings, 1 reply; 170+ messages in thread
From: Mattias Engdegård @ 2020-04-17 16:37 UTC (permalink / raw)
To: 40671; +Cc: Kevin Vigouroux
[-- Attachment #1: Type: text/plain, Size: 422 bytes --]
tags 40671 patch
stop
[Sorry about the truncated message.]
> Can we modify literal objects?
No, and the manual should do a much better job at explaining this. At the very least it should not promulgate bad ideas by including mutation of literals in example code. Patch attached, suggested for emacs-27.
We should not even try to show what happens when the user breaks the rule, because it is undefined.
[-- Attachment #2: 0001-Don-t-mutate-literals-in-manual-examples-bug-40671.patch --]
[-- Type: application/octet-stream, Size: 8588 bytes --]
From 9801ee1b12574f8b1b50ba5b76b7ee41a7fb8bc4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mattias=20Engdeg=C3=A5rd?= <mattiase@acm.org>
Date: Fri, 17 Apr 2020 18:00:34 +0200
Subject: [PATCH] Don't mutate literals in manual examples (bug#40671)
* 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):
Rewrite example code to not mutate constant (literal) lists, vectors
or strings. Noticed by Kevin Vigouroux.
---
doc/lispref/edebug.texi | 2 +-
doc/lispref/keymaps.texi | 8 ++---
doc/lispref/lists.texi | 62 +++++++++-----------------------------
doc/lispref/sequences.texi | 26 ++++++++--------
doc/lispref/strings.texi | 4 +--
5 files changed, 34 insertions(+), 68 deletions(-)
diff --git a/doc/lispref/edebug.texi b/doc/lispref/edebug.texi
index cfef5c12d1..5970e7cf80 100644
--- a/doc/lispref/edebug.texi
+++ b/doc/lispref/edebug.texi
@@ -858,7 +858,7 @@ Printing in Edebug
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 2c90d208c0..fd207a184e 100644
--- a/doc/lispref/keymaps.texi
+++ b/doc/lispref/keymaps.texi
@@ -1441,10 +1441,10 @@ Changing Key Bindings
@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..d1a12e9819 100644
--- a/doc/lispref/lists.texi
+++ b/doc/lispref/lists.texi
@@ -906,7 +906,7 @@ Setcar
@example
@group
-(setq x '(1 2))
+(setq x (list 1 2))
@result{} (1 2)
@end group
@group
@@ -927,7 +927,7 @@ Setcar
@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 +1017,7 @@ Setcdr
@example
@group
-(setq x '(1 2 3))
+(setq x (list 1 2 3))
@result{} (1 2 3)
@end group
@group
@@ -1037,7 +1037,7 @@ Setcdr
@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 +1069,7 @@ Setcdr
@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 +1130,7 @@ Rearrangement
@example
@group
-(setq x '(1 2 3))
+(setq x (list 1 2 3))
@result{} (1 2 3)
@end group
@group
@@ -1150,7 +1150,7 @@ Rearrangement
@example
@group
-(setq x '(1 2 3))
+(setq x (list 1 2 3))
@result{} (1 2 3)
@end group
@group
@@ -1163,41 +1163,7 @@ Rearrangement
@end group
@end example
-However, the other arguments (all but the last) must be 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:
-
-@smallexample
-@group
-(defun add-foo (x) ; @r{We want this function to add}
- (nconc '(foo) x)) ; @r{@code{foo} to the front of its arg.}
-@end group
-
-@group
-(symbol-function 'add-foo)
- @result{} (lambda (x) (nconc '(foo) x))
-@end group
-
-@group
-(setq xx (add-foo '(1 2))) ; @r{It seems to work.}
- @result{} (foo 1 2)
-@end group
-@group
-(setq xy (add-foo '(3 4))) ; @r{What happened?}
- @result{} (foo 1 2 3 4)
-@end group
-@group
-(eq xx xy)
- @result{} t
-@end group
-
-@group
-(symbol-function 'add-foo)
- @result{} (lambda (x) (nconc '(foo 1 2 3 4) x))
-@end group
-@end smallexample
+However, the other arguments (all but the last) must be non-constant lists.
@end defun
@node Sets And Lists
@@ -1260,7 +1226,7 @@ Sets And Lists
@example
@group
-(delq 'a '(a b c)) @equiv{} (cdr '(a b c))
+(delq 'a (list 'a 'b 'c)) @equiv{} (cdr (list 'a 'b 'c))
@end group
@end example
@@ -1270,7 +1236,7 @@ Sets And Lists
@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
@@ -1407,7 +1373,7 @@ Sets And Lists
@example
@group
-(setq l '((2) (1) (2)))
+(setq l (list '(2) '(1) '(2)))
(delete '(2) l)
@result{} ((1))
l
@@ -1416,7 +1382,7 @@ Sets And Lists
;; @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
@@ -1759,7 +1725,7 @@ Association Lists
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 +1892,7 @@ Plist Access
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..d35b4d05e3 100644
--- a/doc/lispref/sequences.texi
+++ b/doc/lispref/sequences.texi
@@ -183,7 +183,7 @@ Sequence Functions
@example
@group
-(setq bar '(1 2))
+(setq bar (list 1 2))
@result{} (1 2)
@end group
@group
@@ -278,7 +278,7 @@ Sequence Functions
@example
@group
-(setq x '(a b c))
+(setq x (list 'a 'b 'c))
@result{} (a b c)
@end group
@group
@@ -374,11 +374,11 @@ Sequence Functions
@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 @@ Sequence Functions
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 @@ Array Functions
@example
@group
-(setq w [foo bar baz])
+(setq w (vector 'foo 'bar 'baz))
@result{} [foo bar baz]
(aset w 0 'fu)
@result{} fu
@@ -1237,12 +1237,12 @@ Array Functions
@end group
@group
-(setq x "asdfasfd")
- @result{} "asdfasfd"
+(setq x (string ?a ?b ?c ?d ?e))
+ @result{} "abcde"
(aset x 3 ?Z)
@result{} 90
x
- @result{} "asdZasfd"
+ @result{} "abcZe"
@end group
@end example
@@ -1257,7 +1257,7 @@ Array Functions
@example
@group
-(setq a [a b c d e f g])
+(setq a (vector '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,10 +1265,10 @@ Array Functions
@result{} [0 0 0 0 0 0 0]
@end group
@group
-(setq s "When in the course")
- @result{} "When in the course"
+(setq s (string ?S ?e ?c ?r ?e ?t))
+ @result{} "Secret"
(fillarray s ?-)
- @result{} "------------------"
+ @result{} "------"
@end group
@end example
diff --git a/doc/lispref/strings.texi b/doc/lispref/strings.texi
index 14cabc5d79..3d375409a9 100644
--- a/doc/lispref/strings.texi
+++ b/doc/lispref/strings.texi
@@ -591,7 +591,7 @@ Text Comparison
@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 +608,7 @@ Text Comparison
@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.21.1 (Apple Git-122.3)
^ permalink raw reply related [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-17 16:37 ` Mattias Engdegård
@ 2020-04-17 17:27 ` Eli Zaretskii
0 siblings, 0 replies; 170+ messages in thread
From: Eli Zaretskii @ 2020-04-17 17:27 UTC (permalink / raw)
To: Mattias Engdegård; +Cc: ke.vigouroux, 40671
> From: Mattias Engdegård <mattiase@acm.org>
> Date: Fri, 17 Apr 2020 18:37:23 +0200
> Cc: Kevin Vigouroux <ke.vigouroux@laposte.net>
>
> > Can we modify literal objects?
>
> No, and the manual should do a much better job at explaining this. At the very least it should not promulgate bad ideas by including mutation of literals in example code. Patch attached, suggested for emacs-27.
I don't see any explanation of the issue in the patch, did I miss
something?
What I see summarily replaces literal lists and cons cells with a
calls to functions, and I'm not sure this is a step in the right
direction. It definitely complicates the examples, which is not
necessarily TRT, methodologically, for such introductory sections.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-16 19:28 bug#40671: [DOC] modify literal objects Kevin Vigouroux via Bug reports for GNU Emacs, the Swiss army knife of text editors
2020-04-17 16:09 ` Mattias Engdegård
@ 2020-04-18 20:10 ` Paul Eggert
2020-04-18 21:54 ` Drew Adams
` (2 more replies)
1 sibling, 3 replies; 170+ messages in thread
From: Paul Eggert @ 2020-04-18 20:10 UTC (permalink / raw)
To: Mattias Engdegård; +Cc: Kevin Vigouroux, 40671-done
[-- Attachment #1: Type: text/plain, Size: 734 bytes --]
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.
[-- Attachment #2: 0001-Document-constant-vs-mutable-objects-better.patch --]
[-- Type: text/x-patch, Size: 19704 bytes --]
From eebfb72c906755c0a80d92c11deee7ac9faf5f4b Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
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
^ permalink raw reply related [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-18 20:10 ` Paul Eggert
@ 2020-04-18 21:54 ` Drew Adams
2020-04-19 2:39 ` Noam Postavsky
` (2 more replies)
2020-04-19 2:26 ` Richard Stallman
2020-04-19 13:56 ` Eli Zaretskii
2 siblings, 3 replies; 170+ messages in thread
From: Drew Adams @ 2020-04-18 21:54 UTC (permalink / raw)
To: Paul Eggert, Mattias Engdegård; +Cc: Kevin Vigouroux, 40671-done
OK, here's a nitpick, FWIW.
___
You say things such as this:
"should be applied only to @dfn{mutable} lists,
that is, lists constructed via @code{cons},
@code{list} or similar operations."
That's not a usual meaning of "mutable". Your
"that is" makes clear what you mean, sort of, I
suppose. That part is clear enough, but it's
not a good "definition" of "mutable".
It's about code that always creates new list
structure, versus code that might create new
list structure only sometimes (e.g. the first
time it's encountered).
A quoted list, which you call "constant", is in
fact mutable in some contexts.
An immutable list would be one you couldn't ever
change - it would truly be a constant. That can
be true for the result of byte-compiling a quoted
list.
But it's not true in general for interpreted
code. E.g., this example in (elisp) `Setcdr':
(setq x '(1 2 3)) ⇒ (1 2 3)
(setcdr x '(4)) ⇒ (4)
x ⇒ (1 4)
What you're really trying to convey presumably
is not that one CANNOT ever modify such a list,
but that one SHOULD NOT modify such a list (e.g.
because of what can happen to it with the byte
compiler). That's something different, and I
don't think the message comes across well.
Similarly:
"However, the other arguments (all but the last)
must be mutable lists."
"MUST" means you CANNOT do otherwise. Trying to
do so might result in an error being raised, for
example. And that's not always the case. Hence
the gotcha, hence the need for a guideline: Don't
do it; just say no.
That text with "must" is immediately followed by:
"A common pitfall is to use a quoted constant list..."
And _that's_ the point. But together with your
text saying you CANNOT modify it anyway, things
get confusing. Modifying a quoted list is
problematic, a gotcha, a pitfall, something to
avoid.
You SHOULD NOT do it precisely because you CAN
do it sometimes. If you couldn't, e.g., if you
were prevented from doing it by always raising
an error, then there would be no gotcha, no
reason to tell you not to do it.
Anyway, you get the idea.
BTW, "a quoted constant list" is a bit poorly
worded, as well. (Yes, that text was already
there.) The problem is using a quoted list
sexp, which can have the effect of producing
a constant list. It's not about quoting a
list that is somehow already a constant.
Quoting can _produce_ a constant.
---
FWIW, Common Lisp doesn't talk about mutable
or immutable lists (or other objects):
"The consequences are undefined if literal
objects (including quoted objects) are
destructively modified."
Undefined. They CAN sometimes be destructively
modified.
And a proposal says to:
"clarify that it is an error to destructively
modify objects which are self-evaluating
forms or which appear inside of a QUOTE
special form."
And it talks of:
"modifying quoted data structures"
Such wording makes clear which things we're
talking about.
Cltl says only:
"implicit sharing of compiled data structures
may result in unpredictable behavior if
destructive operations are performed. However,
CLtL does not explicitly allow or disallow
destructive operations on constants."
Unpredictable behavior. It doesn't say it's
always impossible to modify such things. It
says, in effect, don't try.
That's what we should say for Emacs Lisp, since
we do NOT "disallow modification of constants
consistently in all situations."
For Emacs Lisp this is a gotcha, so we need a
SHOULD. If it were enforced as a MUST then we
wouldn't need such a caveat.
This was proposed for CL:
"Disallowing modification of constants
consistently in all situations, rather than
just in compiled code, is proposed because in
some compiled-only situations it may be
difficult to distinguish between "compiled"
and "interpreted" code."
Whether "disallow" means raise an error in all
such cases (which was proposed for Cltl) or
just warn users not to do it and say the behavior
is "undefined" (what Cltl did, and what Emacs
should do), is a separate question.
The point about trying to modify a quoted list,
for Emacs Lisp, is this:
Don't do it. Don't assume that you get new
list structure each time it looks like a quoted
list will be evaluated anew. It might be
evaluated only once, and the result used as a
constant thereafter.
http://clhs.lisp.se/Issues/iss083_w.htm
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-18 20:10 ` Paul Eggert
2020-04-18 21:54 ` Drew Adams
@ 2020-04-19 2:26 ` Richard Stallman
2020-04-19 13:56 ` Eli Zaretskii
2 siblings, 0 replies; 170+ messages in thread
From: Richard Stallman @ 2020-04-19 2:26 UTC (permalink / raw)
To: Paul Eggert; +Cc: ke.vigouroux, eggert, 40671
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
Thanks to both of you for working on updating the Emacs Lisp Intro.
Its author, Bob Chassell, became incapacitated many years before his
death, so it has not had the needed attention for quite some time. I
would be surprised if it didn't have other problems due to the changes
that we have made in Emacs Lisp since 20 years ago.
Would anyone like to pick some chapter and read it looking for
anything that needs updating? Not only things that are now incorrect,
but anything that is not clear to beginners.
--
Dr Richard Stallman
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-18 21:54 ` Drew Adams
@ 2020-04-19 2:39 ` Noam Postavsky
2020-04-19 20:39 ` Paul Eggert
2020-05-01 3:03 ` Dmitry Gutov
2 siblings, 0 replies; 170+ messages in thread
From: Noam Postavsky @ 2020-04-19 2:39 UTC (permalink / raw)
To: Drew Adams
Cc: Kevin Vigouroux, Mattias Engdegård, Paul Eggert, 40671-done
On Sat, 18 Apr 2020 at 17:55, Drew Adams <drew.adams@oracle.com> wrote:
> An immutable list would be one you couldn't ever
> change - it would truly be a constant. That can
> be true for the result of byte-compiling a quoted
> list.
As far as I know, byte compilation has no special effect on
mutability. Dumping does, or used to, I think that no longer happens
with the pdumper.
.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-18 20:10 ` Paul Eggert
2020-04-18 21:54 ` Drew Adams
2020-04-19 2:26 ` Richard Stallman
@ 2020-04-19 13:56 ` Eli Zaretskii
2020-04-19 16:59 ` Mattias Engdegård
2020-04-19 20:45 ` Paul Eggert
2 siblings, 2 replies; 170+ messages in thread
From: Eli Zaretskii @ 2020-04-19 13:56 UTC (permalink / raw)
To: Paul Eggert; +Cc: mattiase, 40671, ke.vigouroux
> Cc: 40671-done@debbugs.gnu.org, Kevin Vigouroux <ke.vigouroux@laposte.net>,
> Eli Zaretskii <eliz@gnu.org>
> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Sat, 18 Apr 2020 13:10:30 -0700
>
> 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.
How do you know the patch addresses my concerns, when you didn't even
let me read and comment on it? What is this rush to go ahead and push
changes when there's clearly some controversy that hasn't yet been
resolved? Can I somehow convince you not to do that in the future?
> 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.
As Štěpán points out, not all of the examples need these changes.
Please revert the changes that aren't needed.
More generally, it is IMO not enough to explain the issue in one
place, and then use non-literal constructs everywhere as if the reader
magically knows or remembers something that is written in a very far
place of the manual. The effect is to obfuscate the manual without
any explanation right there and then -- which is IMNSHO a very bad
thing, methodologically, because it leaves the readers wondering what
they are missing.
For example, the node "Sets and Lists" now sometimes uses literal
lists and sometimes non-literal ones -- without any explanation why.
Likewise in "Association Lists" and "Sequence Functions".
This is a step backward. We are making our manual a riddle that the
reader will have to solve. That is not how good manuals are written.
> @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
And here you simply changed the meaning of the example: @equiv{} is
not the same as 'equal'.
Bottom line: the extra explanations about the danger of using literal
lists in some situations are a good addition to the manual, but most
of the replacements elsewhere of literal lists with non-literal ones
are not -- unless we also add in each case some text which explains
why we use 'list', 'cons', 'vector', etc, instead of literal
constants.
Please fix these deficiencies.
Thanks in advance.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-19 13:56 ` Eli Zaretskii
@ 2020-04-19 16:59 ` Mattias Engdegård
2020-04-19 19:21 ` Eli Zaretskii
2020-04-19 21:02 ` Paul Eggert
2020-04-19 20:45 ` Paul Eggert
1 sibling, 2 replies; 170+ messages in thread
From: Mattias Engdegård @ 2020-04-19 16:59 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: ke.vigouroux, Paul Eggert, 40671
19 apr. 2020 kl. 15.56 skrev Eli Zaretskii <eliz@gnu.org>:
> This is a step backward. We are making our manual a riddle that the
> reader will have to solve. That is not how good manuals are written.
Eli, maybe that is stretching it a bit? Paul's (and my) changes are far from perfect but they did aim to do no harm. Surely we all prefer correct to simple and wrong. Mistakes must and will be fixed, naturally.
Your point about not surprising the user about inconsistencies in examples is entirely fair, and we should definitely explain these issues more clearly and in the right order. However, it doesn't mean that the status quo ante was better: not only did the manual set bad examples in many places, it even managed to warn sternly about non-constant arguments to nconc right after an example which did precisely that.
What about we add a separate section about literals of all types, why they should be treated as immutable even though mutation currently isn't detected or disallowed at runtime, and recommended ways of coping with it (constructor functions, copy-sequence)? It would serve as a point of reference for all sections describing destructive operations. There is also a need for some cautionary text in the backquote section.
I'd volunteer to write it all but won't do the work just to have it shot down on general principles. It's not like I'm expecting a blank cheque, but we'd need to agree on the approach first.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-19 16:59 ` Mattias Engdegård
@ 2020-04-19 19:21 ` Eli Zaretskii
2020-04-19 21:02 ` Paul Eggert
1 sibling, 0 replies; 170+ messages in thread
From: Eli Zaretskii @ 2020-04-19 19:21 UTC (permalink / raw)
To: Mattias Engdegård; +Cc: ke.vigouroux, eggert, 40671
> From: Mattias Engdegård <mattiase@acm.org>
> Date: Sun, 19 Apr 2020 18:59:55 +0200
> Cc: Paul Eggert <eggert@cs.ucla.edu>, 40671@debbugs.gnu.org,
> ke.vigouroux@laposte.net
>
> 19 apr. 2020 kl. 15.56 skrev Eli Zaretskii <eliz@gnu.org>:
>
> > This is a step backward. We are making our manual a riddle that the
> > reader will have to solve. That is not how good manuals are written.
>
> Eli, maybe that is stretching it a bit? Paul's (and my) changes are far from perfect but they did aim to do no harm. Surely we all prefer correct to simple and wrong. Mistakes must and will be fixed, naturally.
The problem is that the changes were pushed before they could be
reviewed and commented. No one said anything about meaning to do
harm, but mistakes do happen, and a good way to avoid mistakes is to
let peer review take its course. Rushing a commit doesn't allow to
make the changes better by considering aspects that the original
committer was unaware of, or where he/she is biased or lacks some
knowledge or experience that others can contribute.
> Your point about not surprising the user about inconsistencies in examples is entirely fair, and we should definitely explain these issues more clearly and in the right order. However, it doesn't mean that the status quo ante was better: not only did the manual set bad examples in many places, it even managed to warn sternly about non-constant arguments to nconc right after an example which did precisely that.
I stand by what I wrote: the status quo ante was better.
A manual is not a mathematical paper, where everything should be
rigorous all the way from the first page to the last. A good manual
introduces the material gradually, and makes simplifications to avoid
dumping too much stuff on the reader at once. So yes, it is entirely
legitimate to show simplified examples, and at some later point say
that those simple examples have pitfalls, and explain those pitfalls.
There's absolutely no requirement to be 110% correct everywhere in the
manual, because that will make the manual hard to read and understand,
and eventually will shoot us in the foot.
This is, of course, my opinion. Your opinions might be different, and
maybe you could convince me in some of the cases. But for this to
happen, we need to talk, and you (or Paul) need to present the
arguments that aim at changing my mind (or change your own). Is it
too much to ask to let the discussion proceed? If these matters are
important, then we should give their discussion our best shot, so that
the net result is absolutely the best we could come up with -- and
that means it should incorporate the different views and experiences
of most or all the participants.
> What about we add a separate section about literals of all types, why they should be treated as immutable even though mutation currently isn't detected or disallowed at runtime, and recommended ways of coping with it (constructor functions, copy-sequence)? It would serve as a point of reference for all sections describing destructive operations. There is also a need for some cautionary text in the backquote section.
>
> I'd volunteer to write it all but won't do the work just to have it shot down on general principles. It's not like I'm expecting a blank cheque, but we'd need to agree on the approach first.
I don't think I understand the proposal enough to answer the question.
Wed already have a section about these matters, and the additions that
Paul made there are more or less uncontroversial, I think, and
generally consider a Good Thing. What do you suggest in addition to
that?
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-18 21:54 ` Drew Adams
2020-04-19 2:39 ` Noam Postavsky
@ 2020-04-19 20:39 ` Paul Eggert
2020-04-19 21:01 ` Drew Adams
2020-05-01 3:03 ` Dmitry Gutov
2 siblings, 1 reply; 170+ messages in thread
From: Paul Eggert @ 2020-04-19 20:39 UTC (permalink / raw)
To: Drew Adams, Mattias Engdegård; +Cc: Kevin Vigouroux, 40671
On 4/18/20 2:54 PM, Drew Adams wrote:
> "should be applied only to @dfn{mutable} lists,
> that is, lists constructed via @code{cons},
> @code{list} or similar operations."
>
> That's not a usual meaning of "mutable". Your
> "that is" makes clear what you mean, sort of, I
> suppose. That part is clear enough, but it's
> not a good "definition" of "mutable".
>
> It's about code that always creates new list
> structure, versus code that might create new
> list structure only sometimes (e.g. the first
> time it's encountered).
I think we're mostly in agreement here, it's just that it can be difficult to
state things clearly in a reference manual. Let me try to explain a bit further.
As far as Elisp is concerned, it's OK to apply destructive operations to list
structures that are created only sometimes (e.g., the first time it's
encountered), so long as these structures have been created dynamically by the
program. That is, the key notion is not whether the program is implementing
hash-consing on its own (where it's a bad idea to modify already-existing
structures but is valid as far as Elisp is concerned); the key notion here is
whether the program is diving into the Lisp interpreter's data structures and
attempting to change those data structures on the fly (the program shouldn't do
that, as the results are unpredictable and Emacs might crash).
> A quoted list, which you call "constant", is in
> fact mutable in some contexts.
Yes, but we cannot easily document where and when those contexts might be, and
it would be a disservice to our users if we tried to document what happens
exactly, partly because of the complexity and partly because the byte-compiler
might change in the future. Instead, we should simply say that one should not
modify the data structures that quoted lists return.
> An immutable list would be one you couldn't ever
> change - it would truly be a constant. That can
> be true for the result of byte-compiling a quoted
> list.
We can talk about the distinction between a "true constant" and a "constant" in
an introductory section, but in the rest of the manual it's simpler to merely
distinguish between constant objects (which the program should not change) and
mutable objects (which the program can change). That is, in most of the manual
there's no reason to distinguish between the two: modifying a constant is
trouble, and programs shouldn't do it. In the introductory section we can talk
about what happens if programs try to modify a constant anyway.
> "However, the other arguments (all but the last)
> must be mutable lists."
>
> "MUST" means you CANNOT do otherwise.
I changed it to "should".
> BTW, "a quoted constant list" is a bit poorly
> worded, as well.
I changed that to "constant list".
> FWIW, Common Lisp doesn't talk about mutable
> or immutable lists (or other objects):
>
> "The consequences are undefined if literal
> objects (including quoted objects) are
> destructively modified."
>
> Undefined. They CAN sometimes be destructively
> modified.
Yes, that's the idea I'm trying to capture here as well, with the changes I
installed today.
Thanks for your comments.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-19 13:56 ` Eli Zaretskii
2020-04-19 16:59 ` Mattias Engdegård
@ 2020-04-19 20:45 ` Paul Eggert
2020-04-20 14:10 ` Eli Zaretskii
1 sibling, 1 reply; 170+ messages in thread
From: Paul Eggert @ 2020-04-19 20:45 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: mattiase, 40671, ke.vigouroux
[-- Attachment #1: Type: text/plain, Size: 2401 bytes --]
On 4/19/20 6:56 AM, Eli Zaretskii wrote:
> How do you know the patch addresses my concerns
I don't know that; I merely wrote that the patch should address the points you
raised earlier. The goal was to improve documentation that was obviously
deficient in this area - there's no serious dispute about that. The changes I
installed were intended to be an improvement and have been found so by others -
if you disagree, please feel free to revert or improve them. Obviously the
documentation is not perfect in this area and further improvements would be welcome.
> As Štěpán points out, not all of the examples need these changes.
I installed further changes that should address Štěpán's comments.
> For example, the node "Sets and Lists" now sometimes uses literal
> lists and sometimes non-literal ones -- without any explanation why.
> Likewise in "Association Lists" and "Sequence Functions".
This was in response to your request to not change examples if the examples
didn't strictly need the changes. Although I preferred Mattias's original
proposal because it switched to the (list ...) style more uniformly, the patch I
installed mixed the '(...) and (list ...) styles because I thought that was what
you were asking for.
I installed the attached patch, which attempts to address this issue by adding
comments that try to explain why (list ...) is needed sometimes. However, in
hindsight perhaps we should go back to the style used in Mattias's proposal, as
it's simpler and more consistent and doesn't distract the reader from the focus
of the documentation. Going back to Mattias's style would let us remove some of
the comments that the attached patch inserts.
>> @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
>
> And here you simply changed the meaning of the example: @equiv{} is
> not the same as 'equal'.
Ah, I missed on that one. Thanks for pointing it out. I reverted that change in
the attached patch.
As you note, it's not essential that the list be modifiable in this particular
example. That being said, the documentation should not suggest that it's OK to
use a destructive operation like delq on a constant, so further improvements
would be helpful here if someone can find the time.
[-- Attachment #2: 0001-Improve-mutability-doc.patch --]
[-- Type: text/x-patch, Size: 4434 bytes --]
From 5805df74f5b919a3f67f3f7d31d6e600e1564e4e Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Sun, 19 Apr 2020 13:22:10 -0700
Subject: [PATCH] Improve mutability doc
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
See Eli Zaretskii’s suggestions (Bug#40671#33).
* doc/lispref/lists.texi (Setcar, Setcdr, Rearrangement):
* doc/lispref/sequences.texi (Sequence Functions)
(Array Functions):
Add commentary to examples.
* doc/lispref/lists.texi (Sets And Lists):
Revert change to delq example.
---
doc/lispref/lists.texi | 16 +++++++---------
doc/lispref/sequences.texi | 14 ++++++++------
2 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/doc/lispref/lists.texi b/doc/lispref/lists.texi
index f1acc85616..1125af7bec 100644
--- a/doc/lispref/lists.texi
+++ b/doc/lispref/lists.texi
@@ -911,7 +911,7 @@ value @var{object}. For example:
@example
@group
-(setq x (list 1 2))
+(setq x (list 1 2)) ; @r{Create a mutable list.}
@result{} (1 2)
@end group
@group
@@ -931,7 +931,7 @@ these lists. Here is an example:
@example
@group
-;; @r{Create two lists that are partly shared.}
+;; @r{Create two mutable 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))
+(setq x (list 1 2 3)) ; @r{Create a mutable list.}
@result{} (1 2 3)
@end group
@group
-(setcdr x '(4))
+(setcdr x '(4)) ; @r{Modify the list's tail to be a constant list.}
@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))
+(setq x (list 1 2 3)) ; @r{Create a mutable list.}
@result{} (1 2 3)
@end group
@group
-(nconc x '(4 5))
+(nconc x '(4 5)) ; @r{Modify the list's tail to be a constant list.}
@result{} (1 2 3 4 5)
@end group
@group
@@ -1267,9 +1267,7 @@ after those elements. For example:
@example
@group
-(equal
- (delq 'a (list 'a 'b 'c))
- (cdr (list 'a 'b 'c)))
+(delq 'a '(a b c)) @equiv{} (cdr '(a b c))
@end group
@end example
diff --git a/doc/lispref/sequences.texi b/doc/lispref/sequences.texi
index 62d60156fb..1cb0d05cc7 100644
--- a/doc/lispref/sequences.texi
+++ b/doc/lispref/sequences.texi
@@ -183,11 +183,11 @@ for other ways to copy sequences.
@example
@group
-(setq bar (list 1 2))
+(setq bar (list 1 2)) ; @r{Create a mutable list.}
@result{} (1 2)
@end group
@group
-(setq x (vector 'foo bar))
+(setq x (vector 'foo bar)) ; @r{Create a mutable vector.}
@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))
+(setq x (list 'a 'b 'c)) ; @r{Create a mutable list.}
@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]))
+(setq x (copy-sequence [1 2 3 4])) ; @r{Create a mutable vector.}
@result{} [1 2 3 4]
(nreverse x)
@result{} [4 3 2 1]
@@ -374,7 +374,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))
+(setq nums (list 1 3 2 6 5 4 0)) ; @r{Create a mutable list.}
@result{} (1 3 2 6 5 4 0)
@end group
@group
@@ -1228,7 +1228,7 @@ This function sets the @var{index}th element of @var{array} to be
@example
@group
-(setq w (vector 'foo 'bar 'baz))
+(setq w (vector 'foo 'bar 'baz)) ; @r{Create a mutable vector.}
@result{} [foo bar baz]
(aset w 0 'fu)
@result{} fu
@@ -1262,6 +1262,7 @@ 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)
@@ -1270,6 +1271,7 @@ 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 ?-)
--
2.17.1
^ permalink raw reply related [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-19 20:39 ` Paul Eggert
@ 2020-04-19 21:01 ` Drew Adams
2020-04-19 21:16 ` Paul Eggert
0 siblings, 1 reply; 170+ messages in thread
From: Drew Adams @ 2020-04-19 21:01 UTC (permalink / raw)
To: Paul Eggert, Mattias Engdegård; +Cc: Kevin Vigouroux, 40671
> distinguish between constant objects (which the
> program should not change) and mutable objects
> (which the program can change).
That's just not what "constant" means. And I
suspect that your _uses_ of _not_ "mutable" will
still be for things that we really want to say
you probably _should not_ change, and not that
you _cannot_ change them.
You are once again confusing things for readers,
I think.
Something you probably _should not_ change is
not necessarily a constant. (And the converse
isn't strong enough - you simply _cannot_ change
a constant.)
And places where you will likely say there's no
reason you _shouldn't_ change something will
likely give the impression that this is because
it is "mutable", and give the impression that
there's no reason you shouldn't change anything
that you _can_ change. This can give the
impression that if you _can_ change something
(the real meaning of "mutable") then there's no
reason you shouldn't change it. That's the
wrong message.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-19 16:59 ` Mattias Engdegård
2020-04-19 19:21 ` Eli Zaretskii
@ 2020-04-19 21:02 ` Paul Eggert
2020-04-19 21:11 ` Drew Adams
2020-04-19 21:57 ` Michael Heerdegen
1 sibling, 2 replies; 170+ messages in thread
From: Paul Eggert @ 2020-04-19 21:02 UTC (permalink / raw)
To: Mattias Engdegård, Eli Zaretskii; +Cc: ke.vigouroux, 40671
On 4/19/20 9:59 AM, Mattias Engdegård wrote:
> What about we add a separate section about literals of all types, why they should be treated as immutable even though mutation currently isn't detected or disallowed at runtime, and recommended ways of coping with it (constructor functions, copy-sequence)? It would serve as a point of reference for all sections describing destructive operations.
In my recent patches to the emacs-27 branch I added a section "Constants and
Mutability" that discusses many of these issues. It's a fundamental topic so I
put the new section into doc/lispref/objects.texi, and cross-referenced it from
the destructive-operation sections.
I didn't think of recommending ways of coping with it, and that's a good
suggestion. I'm not sure that the coping-mechanism discussion belongs in
objects.texi, though, as it's pragmatic rather than fundamental.
> There is also a need for some cautionary text in the backquote section.
Yes, my recent patches added a brief note there.
> I'd volunteer to write it all but won't do the work just to have it shot down on general principles.
I know the feeling.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-19 21:02 ` Paul Eggert
@ 2020-04-19 21:11 ` Drew Adams
2020-04-19 21:57 ` Michael Heerdegen
1 sibling, 0 replies; 170+ messages in thread
From: Drew Adams @ 2020-04-19 21:11 UTC (permalink / raw)
To: Paul Eggert, Mattias Engdegård, Eli Zaretskii; +Cc: ke.vigouroux, 40671
> In my recent patches to the emacs-27 branch I added a section
> "Constants and Mutability" that discusses many of these issues.
See my previous reply. It's not about (what you called)
constants and mutability. Misleading, and unclear, IMO.
> I didn't think of recommending ways of coping with it
I don't think that's needed. That is, I don't think
there's any such "coping".
What's needed is to make clear to users _what_ happens,
and its effects; that's all. With that info, they can
do whatever's appropriate for them in any given context.
But it's good to show an example of a gotcha, to help
make clear _what_ can happen and why.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-19 21:01 ` Drew Adams
@ 2020-04-19 21:16 ` Paul Eggert
2020-04-19 22:24 ` Drew Adams
0 siblings, 1 reply; 170+ messages in thread
From: Paul Eggert @ 2020-04-19 21:16 UTC (permalink / raw)
To: Drew Adams, Mattias Engdegård; +Cc: Kevin Vigouroux, 40671
On 4/19/20 2:01 PM, Drew Adams wrote:
>> distinguish between constant objects (which the
>> program should not change) and mutable objects
>> (which the program can change).
> That's just not what "constant" means.
What does "constant" mean to you? It's not clear.
> And I
> suspect that your _uses_ of _not_ "mutable" will
> still be for things that we really want to say
> you probably _should not_ change, and not that
> you _cannot_ change them.
Your suspicion is correct. In the current emacs-27 documentation, "mutable"
means you can change the object, "constant" means you should not change it. It's
intended to be documentation that is simple and consistent and tells programmers
what they can do without worrying (change a mutable object), and what they
shouldn't do (try to change a constant).
Of course the documentation could have a more-complex discussion of the various
ways that an object could be "constant". The object could be in read-only memory
enforced by the hardware and operating system, or there could be a run-time
check by the Emacs interpreter, or there could be no check at all and you can
change the constant with the program behaving erratically afterwards, or there
are other possibilities. If you'd like to add text along those lines to the new
section "Constants and Mutability" please feel free to suggest something. The
point is to make that section useful for Emacs Lisp programmers, after all.
> This can give the
> impression that if you _can_ change something
> (the real meaning of "mutable") then there's no
> reason you shouldn't change it.
I'm not following. Even if I've created an object with the 'cons' function there
may be very good pragmatic reasons for me to not invoke setcar and setcdr on it,
as otherwise my program's actions will be scrambled. However, from the Emacs
lisp point of view such a cons is still mutable.
If you propose specific text for the manual, no doubt your point will become
clearer.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-19 21:02 ` Paul Eggert
2020-04-19 21:11 ` Drew Adams
@ 2020-04-19 21:57 ` Michael Heerdegen
2020-04-19 22:41 ` Paul Eggert
1 sibling, 1 reply; 170+ messages in thread
From: Michael Heerdegen @ 2020-04-19 21:57 UTC (permalink / raw)
To: Paul Eggert; +Cc: Mattias Engdegård, 40671, ke.vigouroux
Hello Paul,
I had a quick look at your changes. I agree that it would have been
better to discuss before you start to install what you think you like.
Some things add more confusion. Before your changes the manual used the
term "literal" objects, now you added a different wording "constant"
vs. "mutable" that describes more or less the same thing.
Then some things you added are just wrong, at least in the generality
you word them. As Drew said, `quote' doesn't always return constant
objects, the special form just returns the OBJECT, whatever it is, when
it is evaluated.
Or:
| Vectors written with square brackets are constants and should not be
| modified via @code{aset} or other destructive operations.
(let ((l (list 1 2 3)))
(let ((my-vector `[,@l]))
my-vector))
What does this sentence tell me about the vector I constructed?
We should really be super careful with these changes.
Michael.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-19 21:16 ` Paul Eggert
@ 2020-04-19 22:24 ` Drew Adams
2020-04-19 22:51 ` Paul Eggert
0 siblings, 1 reply; 170+ messages in thread
From: Drew Adams @ 2020-04-19 22:24 UTC (permalink / raw)
To: Paul Eggert, Mattias Engdegård; +Cc: Kevin Vigouroux, 40671
> >> distinguish between constant objects (which the
> >> program should not change) and mutable objects
> >> (which the program can change).
> >
> > That's just not what "constant" means.
>
> What does "constant" mean to you? It's not clear.
Something that remains constant. You simply can't
change it - impossible.
The doc for `defconst' makes clear that it does _not_
define a constant, for example. In what way is what
it defines a variable and not a constant? The fact
that you _can_ change it. If you can change something
then it's not a constant.
The problem is that you're using "constant", NOT for
something that CANNOT be changed, but for something
that you SHOULD NOT try to change. Not the same thing.
> > And I suspect that your _uses_ of _not_ "mutable"
> > will still be for things that we really want to say
> > you probably _should not_ change, and not that
> > you _cannot_ change them.
>
> Your suspicion is correct.
So my suspicion is correct: you're misusing "not
mutable" to mean, not something that can't be
changed but something that probably shouldn't be
changed. See above: not mutable = constant.
> In the current emacs-27 documentation, "mutable"
> means you can change the object,
That contradicts your statement of my suspicion
being correct. If "mutable" means you can change
it (which is truly what it means) then "not mutable"
means you can't change it. It doesn't mean only
that you probably shouldn't change it.
It's the same point. mutable = changeable,
not mutable = constant (not changeable).
You're using "should not" in place of "cannot".
Which means you're also using "no reason not to"
in place of "can".
And the gotcha is precisely that in some cases
where you _can_, you probably _should not_.
> "constant" means you should not change it.
Again, a misuse. "Constant" means truly not mutable,
i.e., you _cannot_ change it.
The message you're giving is backward, or at least
unclear.
Don't say "constant". Say "don't try to change it".
Not because you can't change it (not because it's
constant), but because the code won't necessarily
do what you expect - it might change as you think,
or it might not. That's really the point, I think.
> It's intended to be documentation that is simple
> and consistent
IMO, it's neither. Simple is to just say that you
_cannot depend on_ `quote' (and some other constructs,
no doubt) returning a new object, especially in code
that looks like it would be evaluated multiple times.
And since you can't depend on this, don't. That's
the simple message: "don't do that, because it might
not do what you expect" (when byte-compiled, in
particular).
It might (IMO) be helpful to explain that for
interpreted Elisp source code what you see is what
you get (is that always true?), but the same is not
true for byte-compiled code. And `(quote (A B))'
is a good example.
We probably already say something like that (?) in
other contexts: byte-compiled code may change order
of evaluation or the number of times a subexpression
gets evaluated - for optimization. You can't count
on byte-code acting just like as source code from
which it's compiled would suggest.
> what they shouldn't do (try to change a constant)
No one tries to change a constant. The problem -
the gotcha - is that it's not always obvious when
your code is trying to change a constant. In
particular (but not only), beware of quoted lists.
> Of course the documentation could have a more-complex
> discussion of the various ways that an object could
> be "constant".
And somewhere in the doc that might be helpful, but
only if the particular cases documented are cases we
intend to keep as such. It can happen that we instead
decide to keep that in the dark ("just" implementation),
and we just document that whether XYZ is such a case is
"undefined" - so don't count on it acting as a constant
or not as a constant.
> The object could be in read-only memory enforced by
> the hardware and operating system,
As I said earlier, there's no need to say something's
a constant if it's actually enforced as a constant,
in the sense that an error is raised if you try to
modify it.
The only cases that are problematic are those where
you can think your code modifies something (anew)
when in fact it might not. That's the case we're
talking about wrt quoted list structure.
> > And places where you will likely say there's no
> > reason you _shouldn't_ change something will
> > likely give the impression that this is because
> > it is "mutable", and give the impression that
> > there's no reason you shouldn't change anything
> > that you _can_ change. This can give the
> > impression that if you _can_ change something
> > (the real meaning of "mutable") then there's no
> > reason you shouldn't change it.
>
> I'm not following.
By mischaracterizing not mutable as "should not be
changed" (instead of "cannot be changed"), you can
give the false impression that the opposite is true:
if something is mutable then there's no reason you
shouldn't change it.
Not that the latter follows logically from the former,
but by twisting the meaning of "mutable" all bets in
understanding are off.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-19 21:57 ` Michael Heerdegen
@ 2020-04-19 22:41 ` Paul Eggert
2020-04-19 23:45 ` Michael Heerdegen
2020-04-20 6:02 ` Drew Adams
0 siblings, 2 replies; 170+ messages in thread
From: Paul Eggert @ 2020-04-19 22:41 UTC (permalink / raw)
To: Michael Heerdegen; +Cc: Mattias Engdegård, 40671, ke.vigouroux
On 4/19/20 2:57 PM, Michael Heerdegen wrote:
> I had a quick look at your changes. I agree that it would have been
> better to discuss before you start to install what you think you like.
Yes, in hindsight I suppose you're right. If you like I can revert the changes now.
> Before your changes the manual used the
> term "literal" objects, now you added a different wording "constant"
> vs. "mutable" that describes more or less the same thing.
Thanks, I hadn't recalled that use of "literal object" (in the Equality
Predicates) section. Although the two notions are related they're not identical.
For example, the reason one shouldn't modify byte-code objects is not the
sharing issue mentioned in Equality Predicates: it's because doing so can make
Emacs crash.
That being said, it would be helpful discuss the two notions in a unified way
rather than separately, as is the case now.
> Then some things you added are just wrong, at least in the generality
> you word them. As Drew said, `quote' doesn't always return constant
> objects, the special form just returns the OBJECT, whatever it is, when
> it is evaluated.
It depends on what one means by "constant" objects. If we uniformly changed that
word to "literal" would that remove the objection? For example, although
byte-code objects aren't normally what one would think of as being "literal", we
could simply define them to be "literal".
> | Vectors written with square brackets are constants and should not be
> | modified via @code{aset} or other destructive operations.
>
> (let ((l (list 1 2 3)))
> (let ((my-vector `[,@l]))
> my-vector))
>
> What does this sentence tell me about the vector I constructed?
Nothing, just as the documentation for splicing also says nothing about that
vector. These are both deficiencies in the documentation that should get fixed
(and in some form the deficiencies both predate the recent changes).
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-19 22:24 ` Drew Adams
@ 2020-04-19 22:51 ` Paul Eggert
2020-04-20 5:32 ` Drew Adams
0 siblings, 1 reply; 170+ messages in thread
From: Paul Eggert @ 2020-04-19 22:51 UTC (permalink / raw)
To: Drew Adams, Mattias Engdegård; +Cc: Kevin Vigouroux, 40671
On 4/19/20 3:24 PM, Drew Adams wrote:
> Don't say "constant". Say "don't try to change it".
That's too long and awkward a phrase for use in lots of places around the
manual. We need a simple noun phrase to describe the concept; this is
Documentation 101.
One possible substitute is "literal object", as Mattias pointed out. Another
possibility is "immutable object". Perhaps others might be better.
> The only cases that are problematic are those where
> you can think your code modifies something (anew)
> when in fact it might not.
No, that's not the only issue. If you modify some of these "constants" (or
"literal objects" or whatever term you like), the behavior is undefined: Emacs
can crash or remove your home directory or whatever. There is no checking.
> By mischaracterizing not mutable as "should not be
> changed" (instead of "cannot be changed"), you can
> give the false impression that the opposite is true:
> if something is mutable then there's no reason you
> shouldn't change it.
I don't see that false impression being given. But if it is being given,
presumably the problem could be fixed by appropriate wording changes. Specific
suggestions welcome.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-19 22:41 ` Paul Eggert
@ 2020-04-19 23:45 ` Michael Heerdegen
2020-04-20 0:24 ` Paul Eggert
2020-04-21 1:25 ` Michael Heerdegen
2020-04-20 6:02 ` Drew Adams
1 sibling, 2 replies; 170+ messages in thread
From: Michael Heerdegen @ 2020-04-19 23:45 UTC (permalink / raw)
To: Paul Eggert; +Cc: Mattias Engdegård, 40671, ke.vigouroux
Paul Eggert <eggert@cs.ucla.edu> writes:
> Yes, in hindsight I suppose you're right. If you like I can revert the
> changes now.
I can't estimate, for me it is enough if you are willing to revert if
there is no consent and we discuss all of this now.
> > Before your changes the manual used the
> > term "literal" objects, now you added a different wording "constant"
> > vs. "mutable" that describes more or less the same thing.
>
> Thanks, I hadn't recalled that use of "literal object" (in the
> Equality Predicates) section. Although the two notions are related
> they're not identical. For example, the reason one shouldn't modify
> byte-code objects is not the sharing issue mentioned in Equality
> Predicates: it's because doing so can make Emacs crash.
> That being said, it would be helpful discuss the two notions in a
> unified way rather than separately, as is the case now.
I would like to leave the suggestion of a good wording to someone like
Stefan, feeling not competent enough myself.
I have just the feeling sure if you simplify too much. Lisp has
reading, compiling, evaluation. When the reader reads something like
'(x y z), the (x y z) already produces the literal thing because the
reader transforms it into an object, contrarily to creation of objects
at run-time. The compiler can handle it differently. That's the main
difference. The quote comes into play when the thing gets evaluated.
When you evaluate the expression, the literal is returned. It could
also end up as part of a program, which was the pitfall case in the
initial report.
> > Then some things you added are just wrong, at least in the generality
> > you word them. As Drew said, `quote' doesn't always return constant
> > objects, the special form just returns the OBJECT, whatever it is, when
> > it is evaluated.
>
> It depends on what one means by "constant" objects. If we uniformly
> changed that word to "literal" would that remove the objection? For
> example, although byte-code objects aren't normally what one would
> think of as being "literal", we could simply define them to be
> "literal".
No, that's not (only) what I mean. Maybe you should remember how quote
is used in `defmacro's for example? Generally it's just a mean to
prevent evaluation. In your examples this returned the literal notated
after the quote, but it can be anything.
Or - about what do you speak? The part of the program being quoted, or
the thing "behind" the quote when the program is executed? When you
describe the return value of quote, the special form, in the docstring,
you are speaking about the latter, and then this is wrong, the return
value is the arbitrary OBJECT.
E.g.
(let ((l (list 1 2 3)))
`',l)
==> '(1 2 3)
If you evaluate this (the return value is a valid expression), `quote'
returns a list, but it's not a list literal. But if you try to modify
what the reader constructed after reading ",l", also a list (\, l),
you'll probably get a problem.
As a special case, quote can be used to create lists because Lisp
programs are lists and use list notation anyway. But that's only one
way of using it.
> > | Vectors written with square brackets are constants and should not be
> > | modified via @code{aset} or other destructive operations.
> > (let ((l (list 1 2 3)))
> > (let ((my-vector `[,@l]))
> > my-vector))
> > What does this sentence tell me about the vector I constructed?
>
> Nothing, just as the documentation for splicing also says nothing
> about that vector.
One could read your sentence as suggesting that `my-vector' would be
constant because square brackets are used to construct it. This was an
example to demonstrate where your wording is too vague in my opinion.
Michael.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-19 23:45 ` Michael Heerdegen
@ 2020-04-20 0:24 ` Paul Eggert
2020-04-20 0:53 ` Michael Heerdegen
2020-04-21 1:25 ` Michael Heerdegen
1 sibling, 1 reply; 170+ messages in thread
From: Paul Eggert @ 2020-04-20 0:24 UTC (permalink / raw)
To: Michael Heerdegen; +Cc: Mattias Engdegård, 40671, ke.vigouroux
On 4/19/20 4:45 PM, Michael Heerdegen wrote:
> I have just the feeling sure if you simplify too much. Lisp has
> reading, compiling, evaluation....
Yes, it can be complicated under the hood. The current section attempts to
document this conservatively, saying "If your program does this it'll be safe."
It does not attempt to document much of what happens if you step outside the
"safe" boundaries (i.e., if you attempt to modify "constants" - to use the
current terminology).
One can indeed imagine more-detailed documentation about what happens if you
modify constants. However, I didn't have the time or inclination to document the
details there, and on the whole I think this was the right decision. It's not a
win to greatly complicate the Elisp documentation to cover iffy edge-cases that
code shouldn't be exploring anyway. On the contrary, we should leave things
unspecified in this dangerous area, to give future implementers more freedom to
improve Emacs.
> (let ((l (list 1 2 3)))
> `',l)
>
> ==> '(1 2 3)
>
> If you evaluate this (the return value is a valid expression), `quote'
> returns a list, but it's not a list literal.
Sure, but one shouldn't be modifying that list. Once you hand a Lisp object to
'eval', modifying that object later ought to be a no-no even if the interpreter
happens to do something non-crashy now. Otherwise we're placing too many
constraints on the Lisp implementation (which can crash even now if you play
this sort of game).
>>> | Vectors written with square brackets are constants and should not be
>>> | modified via @code{aset} or other destructive operations.
>>> (let ((l (list 1 2 3)))
>>> (let ((my-vector `[,@l]))
>>> my-vector))
>>> What does this sentence tell me about the vector I constructed?
>>
>> Nothing, just as the documentation for splicing also says nothing
>> about that vector.
>
> One could read your sentence as suggesting that `my-vector' would be
> constant because square brackets are used to construct it. This was an
> example to demonstrate where your wording is too vague in my opinion.
OK, how about if we append the following sentence to that section:
As an exception to the above rules, a vector within a backquote construct
is not considered to be a constant if it contains a substitution or splice.
That is, the backquote causes the vector to (a) not be considered a constant,
(b) be newly created each time the backquote is evaluated, and (c) mutable. The
(a) and (b) parts fix problems that were already there in the longstanding
documentation; the (c) part is new.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-20 0:24 ` Paul Eggert
@ 2020-04-20 0:53 ` Michael Heerdegen
2020-04-20 3:23 ` Paul Eggert
0 siblings, 1 reply; 170+ messages in thread
From: Michael Heerdegen @ 2020-04-20 0:53 UTC (permalink / raw)
To: Paul Eggert; +Cc: Mattias Engdegård, 40671, ke.vigouroux
Paul Eggert <eggert@cs.ucla.edu> writes:
> > (let ((l (list 1 2 3)))
> > `',l)
> > ==> '(1 2 3)
> > If you evaluate this (the return value is a valid expression),
> > `quote'
> > returns a list, but it's not a list literal.
>
> Sure, but one shouldn't be modifying that list. Once you hand a Lisp
> object to 'eval', modifying that object later ought to be a no-no even
> if the interpreter happens to do something non-crashy now.
But I can modify the list before handing it over to `eval',
e.g. replacing the `1' with `cons'.
And even when I eval the original list, I get just the same l as before:
(let ((l (list 1 2 3)))
`',l
(eq l (eval `',l)))
==> t.
AFAIU the problematic entities are the literal lists created by the
reader and the compiler.
> >>> (let ((l (list 1 2 3)))
> >>> (let ((my-vector `[,@l]))
> >>> my-vector))
> OK, how about if we append the following sentence to that section:
>
> As an exception to the above rules, a vector within a backquote construct
> is not considered to be a constant if it contains a substitution or splice.
> That is, the backquote causes the vector to (a) not be considered a
> constant, (b) be newly created each time the backquote is evaluated,
> and (c) mutable. The (a) and (b) parts fix problems that were already
> there in the longstanding documentation; the (c) part is new.
Here your perspective becomes complicated.
The Lisp reader reads the vector [,@l] while reading the program. That
vector is never used by the program, because already the expansion of
the code does not include a vector any more:
(macroexpand-all
'(let ((l (list 1 2 3)))
(let ((my-vector `[,@l]))
my-vector)))
==>
(let
((l (list 1 2 3)))
(let ((my-vector
(vconcat l)))
my-vector))
Only symbols, numbers, and lists.
Any other macro could do something similar, so backquote is not just an
exception, and was only an example that came to my mind first. If the
definition of backquote would try to modify the read [,@l] vector, this
vector of length 1, we would have a problem. But it only analyses this
vector to produce some other code that doesn't even contain a vector any
more.
We must distinguish between the objects created when a program is
read/compiled, i.e. the objects a program consists of (data and programs
are the same in Lisp, etc.), and the objects that that program actually
handles when it runs.
Michael.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-20 0:53 ` Michael Heerdegen
@ 2020-04-20 3:23 ` Paul Eggert
2020-04-20 3:36 ` Michael Heerdegen
2020-04-20 5:54 ` Drew Adams
0 siblings, 2 replies; 170+ messages in thread
From: Paul Eggert @ 2020-04-20 3:23 UTC (permalink / raw)
To: Michael Heerdegen; +Cc: Mattias Engdegård, 40671, ke.vigouroux
On 4/19/20 5:53 PM, Michael Heerdegen wrote:
> Paul Eggert <eggert@cs.ucla.edu> writes:
>
>>> (let ((l (list 1 2 3)))
>>> `',l)
>>> ==> '(1 2 3)
>>> If you evaluate this (the return value is a valid expression),
>>> `quote'
>>> returns a list, but it's not a list literal.
>>
>> Sure, but one shouldn't be modifying that list. Once you hand a Lisp
>> object to 'eval', modifying that object later ought to be a no-no even
>> if the interpreter happens to do something non-crashy now.
>
> But I can modify the list before handing it over to `eval',
> e.g. replacing the `1' with `cons'.
Yes, that's fine. You can modify the list *before* handing it to eval, but it
should be off limits afterwards. That is, the manual doesn't say or imply that
the `,l yields a constant, so the result of the `,l is still modifiable. But
once you hand the list off to eval, watch out: you shouldn't modify it.
Another way to put it is: an object can start off mutable and later become
constant when you start using it as part of a program. Come to think of it,
perhaps this should be added to the Constants and Mutability section. Something
like the following patch, perhaps.
diff --git a/doc/lispref/objects.texi b/doc/lispref/objects.texi
index abd258eb53..dd7eaf5ae4 100644
--- a/doc/lispref/objects.texi
+++ b/doc/lispref/objects.texi
@@ -2400,6 +2400,11 @@ Constants and Mutability
call @code{(make-string 3 ?a)} yields a mutable string that can be
changed via later calls to @code{aset}.
+ A mutable object can become constant if it is passed to the
+@code{eval} function, because you should not modify an object that is
+being or might be executed. The reverse does not occur: constant
+objects should stay constant.
+
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
> And even when I eval the original list, I get just the same l as before:
It's OK that the interpreter does that. But you shouldn't *modify* the original
list after handing it off to eval; it might work and it might not. You shouldn't
even rely on the interpreter giving you the same l as before, for that matter;
that's an implementation detail that is not documented and should not be
documented, any more than we should document the fact that (let ((x (cos 1.5)))
(eq x (+ x))) returns t in Emacs 27.
> We must distinguish between the objects created when a program is
> read/compiled, i.e. the objects a program consists of (data and programs
> are the same in Lisp, etc.), and the objects that that program actually
> handles when it runs.
Yes, and the basic idea is that one cannot reliably modify the objects that a
program consists of while running the program; it's not safe. (All we need to do
is to word this correctly and clearly. :-)
^ permalink raw reply related [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-20 3:23 ` Paul Eggert
@ 2020-04-20 3:36 ` Michael Heerdegen
2020-04-22 6:30 ` Paul Eggert
2020-04-20 5:54 ` Drew Adams
1 sibling, 1 reply; 170+ messages in thread
From: Michael Heerdegen @ 2020-04-20 3:36 UTC (permalink / raw)
To: Paul Eggert; +Cc: Mattias Engdegård, 40671, ke.vigouroux
Paul Eggert <eggert@cs.ucla.edu> writes:
> + A mutable object can become constant if it is passed to the
> +@code{eval} function, because you should not modify an object that is
> +being or might be executed. The reverse does not occur: constant
> +objects should stay constant.
> +
I don't know if what you say about the interpreter is true (I hope it is
not), and I must really go to bed now, but "you should not modify an
object that is being or might be executed" - isn't that quite common
when calculating macro expansions (which, typically, are executed)?
Michael.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-19 22:51 ` Paul Eggert
@ 2020-04-20 5:32 ` Drew Adams
2020-04-22 17:36 ` Paul Eggert
0 siblings, 1 reply; 170+ messages in thread
From: Drew Adams @ 2020-04-20 5:32 UTC (permalink / raw)
To: Paul Eggert, Mattias Engdegård; +Cc: Kevin Vigouroux, 40671
> > Don't say "constant". Say "don't try to change it".
>
> That's too long and awkward a phrase for use in lots
> of places around the manual. We need a simple noun
> phrase to describe the concept; this is Documentation 101.
Giving it an undefined/unexplained name doesn't describe
it at all.
Giving it an existing name (e.g. "constant"), which means
something else, indirectly describes it incorrectly.
Why do we need to say this in "lots of places around
the manual"? Explain the gotcha in one place, and if
need to refer to that explanation elsewhere then do so
(link).
> One possible substitute is "literal object", as Mattias
> pointed out. Another possibility is "immutable object".
> Perhaps others might be better.
As I explained, none of those correspond to what I think
the gotcha is.
> > The only cases that are problematic are those where
> > you can think your code modifies something (anew)
> > when in fact it might not.
>
> No, that's not the only issue. If you modify some of
> these "constants" (or "literal objects" or whatever
> term you like), the behavior is undefined: Emacs can
> crash or remove your home directory or whatever.
If Emacs can crash or remove your home directory,
that's a bug, IMO. We don't document bugs, and we
certainly shouldn't let Emacs crash and just tell
you not to do XYZ because of that.
Saying the behavior in some case is not defined means
(usually) that we're not going to support/guarantee
what the behavior is in that case, and we're not
going to detail/say what it is. Saying some behavior
is undefined is never (in my experience) done knowing
it crashes the program.
> There is no checking.
If that's what's meant then say that.
The explanation of the gotcha should, IMO, include a
simple example of quoting a list: '(1 2 3), and then
modifying some of that list structure.
Say what can happen, e.g. with byte-compilation, and
how that's different from what one might expect if
'(1 2 3) is incorrectly thought of as always creating
new list structure each time that code is evaluated.
Maybe say that just reading the '(1 2 3) creates a
list, and that thereafter that same list is used by
the byte compiler.
The point in showing a simple list example is to
help make clear what's going on. More importantly,
the quoted-list version of the gotcha is the common
one.
I don't want to belabor this. If you don't get what
I'm saying then perhaps someone else will be willing
to explain it better than I. Or if what I've said
is unclear also to others, or is judged wrong, then
please forget about it.
To me, it's pretty simple in terms of effect: You
write '(1 2 3), and you mistakenly think you've
essentially written code that does what (list 1 2 3)
does: creates a new list each time the code it's in
gets evaluated.
Maybe that '(1 2 3) code is in a context where it
(looks like it) gets evaluated more than once.
You think you're getting a new list (new conses)
each time. Some other code modifies the list (e.g.
using setcar). You think that code is modifying
a new list each time, but it's not - it's modifying
the same cons. Gotcha.
There are no doubt other scenarios that exhibit
essentially the same gotcha. But I don't think
it's necessary to detail them all. What's needed
is to provide the warning, some general description
of the problem, and/or a simple example (using a
list).
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-20 3:23 ` Paul Eggert
2020-04-20 3:36 ` Michael Heerdegen
@ 2020-04-20 5:54 ` Drew Adams
2020-04-22 17:21 ` Paul Eggert
1 sibling, 1 reply; 170+ messages in thread
From: Drew Adams @ 2020-04-20 5:54 UTC (permalink / raw)
To: Paul Eggert, Michael Heerdegen
Cc: Mattias Engdegård, 40671, ke.vigouroux
> Another way to put it is: an object can start off mutable and later
> become constant
I don't like that formulation at all. You must
instead be talking about different objects. A
mutable object cannot be changed to a constant,
AFAIK.
I think the gotcha we're talking about is thinking
that a particular object is mutable when it's not.
> +A mutable object can become constant if it is passed to the
> +@code{eval} function,
How so? What's an example?
> +because you should not modify an object that is
> +being or might be executed.
I don't think it even makes any sense to say that
something can become something else _because you
should not do XYZ_. That parses - is grammatical,
but it makes no sense.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-19 22:41 ` Paul Eggert
2020-04-19 23:45 ` Michael Heerdegen
@ 2020-04-20 6:02 ` Drew Adams
1 sibling, 0 replies; 170+ messages in thread
From: Drew Adams @ 2020-04-20 6:02 UTC (permalink / raw)
To: Paul Eggert, Michael Heerdegen
Cc: Mattias Engdegård, 40671, ke.vigouroux
> the reason one shouldn't modify byte-code objects
> is ... because doing so can make Emacs crash.
Really? If something can make Emacs crash it means
there's a bug; that's all. If there's a bug we
shouldn't document the bugged behavior (it should
be fixed), and we especially shouldn't, in the doc,
say "you should [not] do XYZ" because it can make
Emacs crash.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-19 20:45 ` Paul Eggert
@ 2020-04-20 14:10 ` Eli Zaretskii
0 siblings, 0 replies; 170+ messages in thread
From: Eli Zaretskii @ 2020-04-20 14:10 UTC (permalink / raw)
To: Paul Eggert; +Cc: mattiase, 40671, ke.vigouroux
> Cc: mattiase@acm.org, 40671@debbugs.gnu.org, ke.vigouroux@laposte.net
> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Sun, 19 Apr 2020 13:45:07 -0700
>
> > For example, the node "Sets and Lists" now sometimes uses literal
> > lists and sometimes non-literal ones -- without any explanation why.
> > Likewise in "Association Lists" and "Sequence Functions".
>
> This was in response to your request to not change examples if the examples
> didn't strictly need the changes. Although I preferred Mattias's original
> proposal because it switched to the (list ...) style more uniformly, the patch I
> installed mixed the '(...) and (list ...) styles because I thought that was what
> you were asking for.
>
> I installed the attached patch, which attempts to address this issue by adding
> comments that try to explain why (list ...) is needed sometimes.
This is better, thanks. Although my feeling that we complicated what
used to be a simple section is still here.
> However, in
> hindsight perhaps we should go back to the style used in Mattias's proposal, as
> it's simpler and more consistent and doesn't distract the reader from the focus
> of the documentation. Going back to Mattias's style would let us remove some of
> the comments that the attached patch inserts.
I think consistency should take a back seat in these situations.
Clarity and easiness of reading and understanding are much more
important.
> As you note, it's not essential that the list be modifiable in this particular
> example. That being said, the documentation should not suggest that it's OK to
> use a destructive operation like delq on a constant, so further improvements
> would be helpful here if someone can find the time.
But that's exactly the disagreement between us: you think that each
example must be perfect in that it follows all of the principles ever
mentioned anywhere in the manual, and shouldn't go anywhere near the
places which we explain elsewhere are, or might be, dangerous. The
problem with that is that if you want to be absolutely correct and
rigorous, you will more often than not be unable to say anything, or
will produce code samples that are so arcane to the beginner that they
will squarely miss their point. Witness your dialogue with Michael
Heerdegen about related issues.
I think there's no need to assign such crucial importance to every
example. If it is easy to make the example more correct by small
changes, we should consider doing that. But adding the likes of
copy-list to an example that's supposed to show how to delete a list
member is IMO a terrible overkill, and makes the example harder to
understand: a reader who just learned about making and modifying lists
suddenly needs to know what copy-list does (e.g., is it a deep copy or
not?). IMO and IME, this kind of rigor is self-defeating, unless it
comes in a special section marked "Advanced" or somesuch.
Bottom line: IMO the manual should introduce the material gradually;
it is okay to defer some subtle aspects to later sections, and
initially simply disregard them. E.g., in a section that describes
arithmetic operators like '+' in C to someone who is supposed to be a
C beginner, you won't right away talk about integer overflow and the
subsequent danger of crashing the system, and you won't tell the
reader "don't ever use '+', use INT_ADD_WRAPV instead", nor will you
replace examples that use '+' with that macro, would you?
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-19 23:45 ` Michael Heerdegen
2020-04-20 0:24 ` Paul Eggert
@ 2020-04-21 1:25 ` Michael Heerdegen
2020-04-21 2:20 ` Paul Eggert
1 sibling, 1 reply; 170+ messages in thread
From: Michael Heerdegen @ 2020-04-21 1:25 UTC (permalink / raw)
To: Paul Eggert; +Cc: Mattias Engdegård, 40671, ke.vigouroux
Michael Heerdegen <michael_heerdegen@web.de> writes:
> > Yes, in hindsight I suppose you're right. If you like I can revert the
> > changes now.
>
> I can't estimate, for me it is enough if you are willing to revert if
> there is no consent and we discuss all of this now.
But regardless of the impression that your chosen course of action gives
(my own course of action often gives bad impressions for other reasons,
and I don't mean to say that my impression is only bad, just a bit
like...blindside?), it is harder now to review and estimate your changes
in sum, and this is not good for the exchange of views that I think
would be very valuable in this case.
Michael.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-21 1:25 ` Michael Heerdegen
@ 2020-04-21 2:20 ` Paul Eggert
0 siblings, 0 replies; 170+ messages in thread
From: Paul Eggert @ 2020-04-21 2:20 UTC (permalink / raw)
To: Michael Heerdegen; +Cc: Mattias Engdegård, 40671, ke.vigouroux
On 4/20/20 6:25 PM, Michael Heerdegen wrote:
> it is harder now to review and estimate your changes
> in sum
Yes, software archaeology can be a bit of a pain. You could try running this
shell command:
git diff
eebfb72c906755c0a80d92c11deee7ac9faf5f4b^..05089a4d65831c5e873956f5f2d92a3d5672d405
-- doc/lispintro doc/lispref/elisp.texi doc/lispref/eval.texi
doc/lispref/keymaps.texi doc/lispref/lists.texi doc/lispref/objects.texi
doc/lispref/sequences.texi doc/lispref/strings.texi
though if the doc evolves further the command could get longer....
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-20 3:36 ` Michael Heerdegen
@ 2020-04-22 6:30 ` Paul Eggert
0 siblings, 0 replies; 170+ messages in thread
From: Paul Eggert @ 2020-04-22 6:30 UTC (permalink / raw)
To: Michael Heerdegen; +Cc: Mattias Engdegård, 40671, ke.vigouroux
On 4/19/20 8:36 PM, Michael Heerdegen wrote:
> Paul Eggert <eggert@cs.ucla.edu> writes:
>
>> + A mutable object can become constant if it is passed to the
>> +@code{eval} function, because you should not modify an object that is
>> +being or might be executed. The reverse does not occur: constant
>> +objects should stay constant.
>> +
>
> I don't know if what you say about the interpreter is true (I hope it is
> not),
Unfortunately it is true, for performance reasons: you can't reliably change a
form that is currently being executed by the Lisp interpreter. This is because
the interpreter can cache parts of such forms, or can check forms and later
execute them under the assumption that the checks succeeded, and if the caches
are invalid or the earlier checks no longer apply then Emacs can dump core or worse.
> "you should not modify an
> object that is being or might be executed" - isn't that quite common
> when calculating macro expansions (which, typically, are executed)?
You can modify the object before giving it to 'eval' (and macro expansion can do
modifications like that), but you shouldn't modify it while it's being evaluated.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-20 5:54 ` Drew Adams
@ 2020-04-22 17:21 ` Paul Eggert
2020-04-23 0:49 ` Michael Heerdegen
0 siblings, 1 reply; 170+ messages in thread
From: Paul Eggert @ 2020-04-22 17:21 UTC (permalink / raw)
To: Drew Adams, Michael Heerdegen; +Cc: Mattias Engdegård, 40671, ke.vigouroux
On 4/19/20 10:54 PM, Drew Adams wrote:
> A mutable object cannot be changed to a constant
Sure they can. This idea is common in other languages, e.g., see Object.freeze
method in JavaScript. There's no reason Emacs Lisp can't use the idea.
>> +A mutable object can become constant if it is passed to the
>> +@code{eval} function,
>
> How so? What's an example?
(let ((x (make-string 1 ?a)))
(eval `(progn
(defun foo ()
(let ((a ,x))
(aset x 0 ?b)
(list a "a" (equal a "a"))))
(byte-compile 'foo)
(foo))))
This code is not well-formed because it modifies the string x after passing it
to eval (such strings should be constant). As a result, the behavior of the
program is unpredictable. On master it currently yields ("b" "b" t) but there's
no guarantee of this.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-20 5:32 ` Drew Adams
@ 2020-04-22 17:36 ` Paul Eggert
0 siblings, 0 replies; 170+ messages in thread
From: Paul Eggert @ 2020-04-22 17:36 UTC (permalink / raw)
To: Drew Adams, Mattias Engdegård; +Cc: Kevin Vigouroux, 40671
On 4/19/20 10:32 PM, Drew Adams wrote:
> Giving it an existing name (e.g. "constant"), which means
> something else
In informal language the word "constant" can mean different things to different
people. If the manual defines the word "constant" to mean "an object whose value
should never change" and it uses that word consistently, then that's OK; the
manual's terminology corresponds closely enough to the informal one. Of course
if we can come up with a better phrase than "constant" then we should use that;
but so far we haven't seemed to be able to.
> Explain the gotcha in one place, and if
> need to refer to that explanation elsewhere then do so
> (link).
Yes, that's what's done now.
> If Emacs can crash or remove your home directory,
> that's a bug, IMO. We don't document bugs
We should advise Lisp programmers about what they can do safely, and what they
should not do due to Emacs's unfortunate limitations. We already do this in
other dangerous areas (e.g., what happens if you increase max-lisp-eval-depth
too far), and we should do it in this dangerous area too. You're right that we
needn't document in detail what happens if a Lisp program does unsafe things.
> we certainly shouldn't let Emacs crash
If we can fix the problem that would be better, yes. However, it's not practical
to do that for Emacs 27 because it is so close to release and any fix would
require major surgery. It's not clear that it's practical to fix things even for
Emacs 28.
> Saying some behavior
> is undefined is never (in my experience) done knowing
> it crashes the program.
Welcome to the wonderful world of undefined behavior. I'm joking of course;
undefined behavior is not a good thing. But here we are.
> Maybe say that just reading the '(1 2 3) creates a
> list, and that thereafter that same list is used by
> the byte compiler.
Thanks, I'll add something along those lines.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-22 17:21 ` Paul Eggert
@ 2020-04-23 0:49 ` Michael Heerdegen
2020-04-24 2:36 ` Richard Stallman
2020-04-25 2:22 ` Paul Eggert
0 siblings, 2 replies; 170+ messages in thread
From: Michael Heerdegen @ 2020-04-23 0:49 UTC (permalink / raw)
To: Paul Eggert; +Cc: Mattias Engdegård, 40671, ke.vigouroux
Paul Eggert <eggert@cs.ucla.edu> writes:
> > A mutable object cannot be changed to a constant
>
> Sure they can. This idea is common in other languages, e.g., see
> Object.freeze method in JavaScript. There's no reason Emacs Lisp can't
> use the idea.
Ok. I still have questions and objections about your additions:
+ A mutable object can become constant if it is passed to the
+@code{eval} function, because you should not modify an object that is
+being or might be executed. The reverse does not occur: constant
+objects should stay constant.
`eval' is used quite rarely. Can what you describe happen under other
circumstances, or does it only happen to `eval'? E.g. what about this
case for example:
(let ((l (list 1 2 3)))
(funcall (lambda () l)))
Has the list become a constant?
I ask because the sub-clause "because you should not modify an object
that is being or might be executed" is totally different statement than
that about `eval'. A list literal (1 2 3) or a string as in the example
in your answer to Drew are surely not executed, as they are not valid
forms. They are part of a program. But anything a macro generates also
becomes part of a program. Maybe I misread "might be executed" as
"might be executed in the future" and you actually meant something like
"might (currently) be executed (as part of the expression the
interpreter currently executes).
BTW, speaking about Lisp the term "evaluate" is probably preferable to
"execute" I think.
Thanks,
Michael.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-23 0:49 ` Michael Heerdegen
@ 2020-04-24 2:36 ` Richard Stallman
2020-04-24 15:08 ` Drew Adams
2020-04-24 16:39 ` Mattias Engdegård
2020-04-25 2:22 ` Paul Eggert
1 sibling, 2 replies; 170+ messages in thread
From: Richard Stallman @ 2020-04-24 2:36 UTC (permalink / raw)
To: Michael Heerdegen; +Cc: mattiase, eggert, 40671, ke.vigouroux
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
It seems strange to use the terms "constant" and "mutable" to describe
whether modifying its contents is something you had better avoid.
I think people will find that terminology confusing. Normally
"mutable" means that you CAN change it, not that it is OK to change it.
--
Dr Richard Stallman
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-24 2:36 ` Richard Stallman
@ 2020-04-24 15:08 ` Drew Adams
2020-04-25 1:58 ` Paul Eggert
2020-04-24 16:39 ` Mattias Engdegård
1 sibling, 1 reply; 170+ messages in thread
From: Drew Adams @ 2020-04-24 15:08 UTC (permalink / raw)
To: rms, Michael Heerdegen; +Cc: mattiase, eggert, 40671, ke.vigouroux
> It seems strange to use the terms "constant" and "mutable" to describe
> whether modifying its contents is something you had better avoid.
> I think people will find that terminology confusing. Normally
> "mutable" means that you CAN change it, not that it is OK to change it.
Yes. Precisely what I, Michael, and others said.
The message should be one of advice/guidance:
explaining a gotcha, or at least suggesting what
to avoid.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-24 2:36 ` Richard Stallman
2020-04-24 15:08 ` Drew Adams
@ 2020-04-24 16:39 ` Mattias Engdegård
2020-04-24 16:46 ` Dmitry Gutov
` (2 more replies)
1 sibling, 3 replies; 170+ messages in thread
From: Mattias Engdegård @ 2020-04-24 16:39 UTC (permalink / raw)
To: Richard Stallman; +Cc: Michael Heerdegen, ke.vigouroux, eggert, 40671
24 apr. 2020 kl. 04.36 skrev Richard Stallman <rms@gnu.org>:
> It seems strange to use the terms "constant" and "mutable" to describe
> whether modifying its contents is something you had better avoid.
> I think people will find that terminology confusing. Normally
> "mutable" means that you CAN change it, not that it is OK to change it.
That is an interesting point. What is the difference between CANNOT and SHOULD NOT, operationally? To the user, nothing; there is no gain from disobeying our advice. Implementation-wise, it's whether there are strong checks or not. (For example, in C you should not read from already freed memory, but there is no mechanism actually preventing you from doing so.)
It's useful to have the option to add strong checks, so that (setcar '(1 . 2) 3) throws an error. Then, what used to be SHOULD NOT turns into CANNOT, but the attentive user has no reason to change behaviour.
Of course the real world is messy and people sometimes have code that breaks the rules but still seem to work. There would need to be a transition period, and a switch to run in a permissive mode.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-24 16:39 ` Mattias Engdegård
@ 2020-04-24 16:46 ` Dmitry Gutov
2020-04-25 2:21 ` Paul Eggert
2020-04-24 17:18 ` Drew Adams
2020-04-25 3:38 ` Richard Stallman
2 siblings, 1 reply; 170+ messages in thread
From: Dmitry Gutov @ 2020-04-24 16:46 UTC (permalink / raw)
To: Mattias Engdegård, Richard Stallman
Cc: Michael Heerdegen, ke.vigouroux, eggert, 40671
On 24.04.2020 19:39, Mattias Engdegård wrote:
> That is an interesting point. What is the difference between CANNOT and SHOULD NOT, operationally? To the user, nothing; there is no gain from disobeying our advice.
The difference is at runtime, obviously. And the problem is using the
words in a way that differs from other programming languages, for instance.
> It's useful to have the option to add strong checks, so that (setcar '(1 . 2) 3) throws an error. Then, what used to be SHOULD NOT turns into CANNOT, but the attentive user has no reason to change behaviour.
*If* we do that, we could call them constants. But I imagine we never
will, for backward compatibility reasons. Emacs core itself modifies
these "constants" at runtime in quite a few places, I'm sure.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-24 16:39 ` Mattias Engdegård
2020-04-24 16:46 ` Dmitry Gutov
@ 2020-04-24 17:18 ` Drew Adams
2020-04-25 3:38 ` Richard Stallman
2 siblings, 0 replies; 170+ messages in thread
From: Drew Adams @ 2020-04-24 17:18 UTC (permalink / raw)
To: Mattias Engdegård, Richard Stallman
Cc: Michael Heerdegen, ke.vigouroux, eggert, 40671
> > It seems strange to use the terms "constant" and "mutable" to
> > describe whether modifying its contents is something you had
> > better avoid. I think people will find that terminology
> > confusing. Normally "mutable" means that you CAN change it,
> > not that it is OK to change it.
>
> What is the difference between CANNOT and
> SHOULD NOT, operationally? To the user, nothing; there is no gain from
> disobeying our advice.
No. To the user: something. And the negative
effects might not be immediately noticeable.
If we say that you can't modify XYZ there's no
need for you to pay attention, learn about the
gotcha, and try to avoid modifying XYZ.
The burden here is on the user (unfortunately).
Emacs Lisp doesn't protect you from doing what
you'd be told you "cannot" do. It's up to you
to know when you might be stumbling onto this
pitfall and avoid it.
Telling users they _can't_ fall into this pit
is like telling someone it's impossible for their
car to go through a red light. Nope, they're the
driver, and the message should be, "Don't drive
through a red light."
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-24 15:08 ` Drew Adams
@ 2020-04-25 1:58 ` Paul Eggert
0 siblings, 0 replies; 170+ messages in thread
From: Paul Eggert @ 2020-04-25 1:58 UTC (permalink / raw)
To: Drew Adams, rms, Michael Heerdegen; +Cc: mattiase, 40671, ke.vigouroux
On 4/24/20 8:08 AM, Drew Adams wrote:
> The message should be one of advice/guidance:
> explaining a gotcha, or at least suggesting what
> to avoid.
That's what the current emacs-27 manual does, or tries to do. If it doesn't do
so clearly enough, specific suggestions for improving the wording would be helpful.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-24 16:46 ` Dmitry Gutov
@ 2020-04-25 2:21 ` Paul Eggert
2020-04-25 2:40 ` Dmitry Gutov
0 siblings, 1 reply; 170+ messages in thread
From: Paul Eggert @ 2020-04-25 2:21 UTC (permalink / raw)
To: Dmitry Gutov, Mattias Engdegård, Richard Stallman
Cc: Michael Heerdegen, ke.vigouroux, 40671
On 4/24/20 9:46 AM, Dmitry Gutov wrote:
> On 24.04.2020 19:39, Mattias Engdegård wrote:
>> That is an interesting point. What is the difference between CANNOT and SHOULD
>> NOT, operationally? To the user, nothing; there is no gain from disobeying our
>> advice.
>
> The difference is at runtime, obviously. And the problem is using the words in a
> way that differs from other programming languages, for instance.
That depends on what other programming languages we're talking about. The
current use of 'constant' in the manual corresponds reasonably closely to
'const' objects in C and C++.
>> It's useful to have the option to add strong checks, so that (setcar '(1 . 2)
>> 3) throws an error. Then, what used to be SHOULD NOT turns into CANNOT, but
>> the attentive user has no reason to change behaviour.
>
> *If* we do that, we could call them constants. But I imagine we never will, for
> backward compatibility reasons. Emacs core itself modifies these "constants" at
> runtime in quite a few places, I'm sure.
Actually Emacs formerly was more careful about this sort of thing: more objects
were constant and Emacs reliably signaled an error if you tried to change them.
If we brought back this feature we'd actually be more backwards-compatible than
we already are, at least in some sense. I expect it'd be a good thing to do if
it didn't hurt performance, as it should help reliability/safety a bit.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-23 0:49 ` Michael Heerdegen
2020-04-24 2:36 ` Richard Stallman
@ 2020-04-25 2:22 ` Paul Eggert
2020-04-25 6:00 ` Andreas Schwab
2020-04-28 23:52 ` Michael Heerdegen
1 sibling, 2 replies; 170+ messages in thread
From: Paul Eggert @ 2020-04-25 2:22 UTC (permalink / raw)
To: Michael Heerdegen; +Cc: Mattias Engdegård, 40671, ke.vigouroux
[-- Attachment #1: Type: text/plain, Size: 1399 bytes --]
On 4/22/20 5:49 PM, Michael Heerdegen wrote:
> + A mutable object can become constant if it is passed to the
> +@code{eval} function, because you should not modify an object that is
> +being or might be executed. The reverse does not occur: constant
> +objects should stay constant.
>
> `eval' is used quite rarely. Can what you describe happen under other
> circumstances, or does it only happen to `eval'? E.g. what about this
> case for example:
>
> (let ((l (list 1 2 3)))
> (funcall (lambda () l)))
>
> Has the list become a constant?
No, because the list is not part of the expression that is being evaluated.
However, something like this could cause trouble:
(let ((l (list 'lambda '(x) '(setcdr l x))))
(eval (list l l)))
because it modifies the list l while it is evaluating it. (As it happens, this
code behaves differently in Emacs 26 than it does in Emacs 27 - that's what you
can get with undefined behavior....)
> Maybe I misread "might be executed" as
> "might be executed in the future" and you actually meant something like
> "might (currently) be executed (as part of the expression the
> interpreter currently executes).
>
> BTW, speaking about Lisp the term "evaluate" is probably preferable to
> "execute" I think.
Both good points. The word "executed" is already gone from the manual, and I
installed the attached patch to try to address the other point.
[-- Attachment #2: 0001-Tweak-mutability-doc-a-bit-more.patch --]
[-- Type: text/x-patch, Size: 1118 bytes --]
From 49bc5a63f7d6178f136d9e28bcacda3acfc375d3 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Fri, 24 Apr 2020 19:19:31 -0700
Subject: [PATCH] Tweak mutability doc a bit more
Inspired by a comment from Michael Heerdegen (Bug#40671#114).
* doc/lispref/objects.texi (Constants and Mutability): Tweak further.
---
doc/lispref/objects.texi | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/doc/lispref/objects.texi b/doc/lispref/objects.texi
index 1eda94ab63..b4e9ff4411 100644
--- a/doc/lispref/objects.texi
+++ b/doc/lispref/objects.texi
@@ -2401,8 +2401,8 @@ Constants and Mutability
call @code{(make-string 3 ?a)} yields a mutable string that can be
changed via later calls to @code{aset}.
- A mutable object can become constant if it is passed to the
-@code{eval} function, because a program should not modify an object
+ A mutable object can become constant if it is part of an expression
+that is evaluated, because a program should not modify an object
that is being evaluated. The reverse does not occur: constant objects
should stay constant.
--
2.17.1
^ permalink raw reply related [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-25 2:21 ` Paul Eggert
@ 2020-04-25 2:40 ` Dmitry Gutov
2020-04-25 3:20 ` Paul Eggert
0 siblings, 1 reply; 170+ messages in thread
From: Dmitry Gutov @ 2020-04-25 2:40 UTC (permalink / raw)
To: Paul Eggert, Mattias Engdegård, Richard Stallman
Cc: Michael Heerdegen, ke.vigouroux, 40671
On 25.04.2020 05:21, Paul Eggert wrote:
> That depends on what other programming languages we're talking about. The
> current use of 'constant' in the manual corresponds reasonably closely to
> 'const' objects in C and C++.
Since we're talking about non-scalar values, do you mean constant
pointers to (generally) mutable objects? Or a constant aggregate of
mutable objects?
When a value is constant in C or C++, you can't change it.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-25 2:40 ` Dmitry Gutov
@ 2020-04-25 3:20 ` Paul Eggert
2020-04-25 19:30 ` Dmitry Gutov
0 siblings, 1 reply; 170+ messages in thread
From: Paul Eggert @ 2020-04-25 3:20 UTC (permalink / raw)
To: Dmitry Gutov, Mattias Engdegård, Richard Stallman
Cc: Michael Heerdegen, ke.vigouroux, 40671
On 4/24/20 7:40 PM, Dmitry Gutov wrote:
>> That depends on what other programming languages we're talking about. The
>> current use of 'constant' in the manual corresponds reasonably closely to
>> 'const' objects in C and C++.
>
> Since we're talking about non-scalar values, do you mean constant pointers to
> (generally) mutable objects? Or a constant aggregate of mutable objects?
Neither. I mean a constant object, e.g., the array of chars denoted by the
string literal "abc" in C.
> When a value is constant in C or C++, you can't change it.
Yes, you can't change it in a portable program, because if you attempt to change
it the resulting behavior is undefined. The attempt might succeed so that the
"constant" is changed, or you might get a core dump, or you might get an
exception, or something else might happen.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-24 16:39 ` Mattias Engdegård
2020-04-24 16:46 ` Dmitry Gutov
2020-04-24 17:18 ` Drew Adams
@ 2020-04-25 3:38 ` Richard Stallman
2020-04-25 18:26 ` Paul Eggert
2 siblings, 1 reply; 170+ messages in thread
From: Richard Stallman @ 2020-04-25 3:38 UTC (permalink / raw)
To: Mattias Engdegård
Cc: michael_heerdegen, ke.vigouroux, eggert, 40671
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> That is an interesting point. What is the difference between
> CANNOT and SHOULD NOT, operationally? To the user, nothing; there
> is no gain from disobeying our advice.
It makes a big practical difference to programmers.
CANNOT means "If you try to chsnge it, it won't change",
and probably also "That will trigger a diagnostic."
SHOULOD NOT means "if you try to chsnge it, it will give you no
diagnostic and the value will seem to have changed, but afterward
bizarre things may happen."
--
Dr Richard Stallman
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-25 2:22 ` Paul Eggert
@ 2020-04-25 6:00 ` Andreas Schwab
2020-04-25 18:23 ` Paul Eggert
2020-04-28 23:52 ` Michael Heerdegen
1 sibling, 1 reply; 170+ messages in thread
From: Andreas Schwab @ 2020-04-25 6:00 UTC (permalink / raw)
To: Paul Eggert
Cc: Michael Heerdegen, Mattias Engdegård, 40671, ke.vigouroux
On Apr 24 2020, Paul Eggert wrote:
> diff --git a/doc/lispref/objects.texi b/doc/lispref/objects.texi
> index 1eda94ab63..b4e9ff4411 100644
> --- a/doc/lispref/objects.texi
> +++ b/doc/lispref/objects.texi
> @@ -2401,8 +2401,8 @@ Constants and Mutability
> call @code{(make-string 3 ?a)} yields a mutable string that can be
> changed via later calls to @code{aset}.
>
> - A mutable object can become constant if it is passed to the
> -@code{eval} function, because a program should not modify an object
> + A mutable object can become constant if it is part of an expression
> +that is evaluated, because a program should not modify an object
> that is being evaluated. The reverse does not occur: constant objects
"that is evaluated ... that is being evaluated" is saying the same thing
twice.
Andreas.
--
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510 2552 DF73 E780 A9DA AEC1
"And now for something completely different."
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-25 6:00 ` Andreas Schwab
@ 2020-04-25 18:23 ` Paul Eggert
0 siblings, 0 replies; 170+ messages in thread
From: Paul Eggert @ 2020-04-25 18:23 UTC (permalink / raw)
To: Andreas Schwab
Cc: Michael Heerdegen, Mattias Engdegård, 40671, ke.vigouroux
[-- Attachment #1: Type: text/plain, Size: 181 bytes --]
On 4/24/20 11:00 PM, Andreas Schwab wrote:
> "that is evaluated ... that is being evaluated" is saying the same thing
> twice.
Thanks for catching that; I installed the attached.
[-- Attachment #2: 0001-Remove-doc-duplication.patch --]
[-- Type: text/x-patch, Size: 1027 bytes --]
From 9621a4840a27d2fb0283a4faa5aadd7febaeaf6b Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Sat, 25 Apr 2020 11:22:01 -0700
Subject: [PATCH] Remove doc duplication
* doc/lispref/objects.texi (Constants and Mutability): Remove
duplication. From a suggestion by Andreas Schwab (Bug#40671#150).
---
doc/lispref/objects.texi | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/doc/lispref/objects.texi b/doc/lispref/objects.texi
index b4e9ff4411..1d5b2c690f 100644
--- a/doc/lispref/objects.texi
+++ b/doc/lispref/objects.texi
@@ -2402,8 +2402,7 @@ Constants and Mutability
changed via later calls to @code{aset}.
A mutable object can become constant if it is part of an expression
-that is evaluated, because a program should not modify an object
-that is being evaluated. The reverse does not occur: constant objects
+that is evaluated. The reverse does not occur: constant objects
should stay constant.
Trying to modify a constant variable signals an error
--
2.17.1
^ permalink raw reply related [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-25 3:38 ` Richard Stallman
@ 2020-04-25 18:26 ` Paul Eggert
0 siblings, 0 replies; 170+ messages in thread
From: Paul Eggert @ 2020-04-25 18:26 UTC (permalink / raw)
To: rms, Mattias Engdegård; +Cc: michael_heerdegen, ke.vigouroux, 40671
On 4/24/20 8:38 PM, Richard Stallman wrote:
> SHOULOD NOT means "if you try to change it, it will give you no
> diagnostic and the value will seem to have changed, but afterward
> bizarre things may happen."
Here SHOULD NOT simply means "if you try to change it, afterward bizarre things
may happen". This includes the meaning you gave, and also includes some other
meanings.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-25 3:20 ` Paul Eggert
@ 2020-04-25 19:30 ` Dmitry Gutov
2020-04-26 3:49 ` Paul Eggert
0 siblings, 1 reply; 170+ messages in thread
From: Dmitry Gutov @ 2020-04-25 19:30 UTC (permalink / raw)
To: Paul Eggert, Mattias Engdegård, Richard Stallman
Cc: Michael Heerdegen, ke.vigouroux, 40671
On 25.04.2020 06:20, Paul Eggert wrote:
>> When a value is constant in C or C++, you can't change it.
> Yes, you can't change it in a portable program, because if you attempt to change
> it the resulting behavior is undefined. The attempt might succeed so that the
> "constant" is changed, or you might get a core dump, or you might get an
> exception, or something else might happen.
Might succeed? Will it even compile?
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-25 19:30 ` Dmitry Gutov
@ 2020-04-26 3:49 ` Paul Eggert
2020-04-26 14:03 ` Dmitry Gutov
0 siblings, 1 reply; 170+ messages in thread
From: Paul Eggert @ 2020-04-26 3:49 UTC (permalink / raw)
To: Dmitry Gutov, Mattias Engdegård, Richard Stallman
Cc: Michael Heerdegen, ke.vigouroux, 40671
On 4/25/20 12:30 PM, Dmitry Gutov wrote:
> On 25.04.2020 06:20, Paul Eggert wrote:
>>> When a value is constant in C or C++, you can't change it.
>> Yes, you can't change it in a portable program, because if you attempt to change
>> it the resulting behavior is undefined. The attempt might succeed so that the
>> "constant" is changed, or you might get a core dump, or you might get an
>> exception, or something else might happen.
>
> Might succeed? Will it even compile?
Yes, although the C/C++ program must type-check and satisfy all other static
constraints of course (otherwise it won't compile). Here's a simple example:
#include <string.h>
int main (void) { return !strcpy ("a", "b"); }
This function attempts to modify the "a" string constant, so it might dump core,
or might return 0, or might do other things.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-26 3:49 ` Paul Eggert
@ 2020-04-26 14:03 ` Dmitry Gutov
2020-04-26 14:19 ` Eli Zaretskii
2020-04-26 18:57 ` Paul Eggert
0 siblings, 2 replies; 170+ messages in thread
From: Dmitry Gutov @ 2020-04-26 14:03 UTC (permalink / raw)
To: Paul Eggert, Mattias Engdegård, Richard Stallman
Cc: Michael Heerdegen, ke.vigouroux, 40671
On 26.04.2020 06:49, Paul Eggert wrote:
>> Might succeed? Will it even compile?
> Yes, although the C/C++ program must type-check and satisfy all other static
> constraints of course (otherwise it won't compile). Here's a simple example:
>
> #include <string.h>
> int main (void) { return !strcpy ("a", "b"); }
>
> This function attempts to modify the "a" string constant, so it might dump core,
> or might return 0, or might do other things.
g++ string_const.c++
string_const.c++: In function ‘int main()’:
string_const.c++:2:35: warning: ISO C++ forbids converting a string
constant to ‘char*’ [-Wwrite-strings]
2 | int main (void) { return !strcpy ("a", "b"); }
I have no idea why it only shows a compile-time warning (probably
because of backward-compatibility concerns because in C a string is
*not* a const, just a source of undefined behavior), but the warning, at
least, is there for the user to see. Not just in the manual.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-26 14:03 ` Dmitry Gutov
@ 2020-04-26 14:19 ` Eli Zaretskii
2020-04-26 14:34 ` Dmitry Gutov
2020-04-26 18:57 ` Paul Eggert
1 sibling, 1 reply; 170+ messages in thread
From: Eli Zaretskii @ 2020-04-26 14:19 UTC (permalink / raw)
To: Dmitry Gutov
Cc: ke.vigouroux, eggert, 40671, michael_heerdegen, mattiase, rms
> From: Dmitry Gutov <dgutov@yandex.ru>
> Date: Sun, 26 Apr 2020 17:03:38 +0300
> Cc: Michael Heerdegen <michael_heerdegen@web.de>, ke.vigouroux@laposte.net,
> 40671@debbugs.gnu.org
>
> > #include <string.h>
> > int main (void) { return !strcpy ("a", "b"); }
> >
> > This function attempts to modify the "a" string constant, so it might dump core,
> > or might return 0, or might do other things.
>
> g++ string_const.c++
> string_const.c++: In function ‘int main()’:
> string_const.c++:2:35: warning: ISO C++ forbids converting a string
> constant to ‘char*’ [-Wwrite-strings]
> 2 | int main (void) { return !strcpy ("a", "b"); }
Did you try compiling that as a C program, not a C++ program?
If I force the C compiler to use -Wwrite-strings, then I get:
gcc -Wwrite-strings string_const.c
string_const.c: In function 'main':
string_const.c:2:35: warning: passing argument 1 of 'strcpy' discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]
int main (void) { return !strcpy ("a", "b"); }
^~~
In file included from string_const.c:1:0:
d:\usr\include\string.h:79:40: note: expected 'char *' but argument is of type 'const char *'
_CRTIMP __cdecl __MINGW_NOTHROW char *strcpy (char *, const char *);
^~~~~~
but even that goes away if I modify the program as follows:
#include <string.h>
int main (void) { return !strcpy ((char *)"a", "b"); }
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-26 14:19 ` Eli Zaretskii
@ 2020-04-26 14:34 ` Dmitry Gutov
2020-04-26 15:46 ` Eli Zaretskii
0 siblings, 1 reply; 170+ messages in thread
From: Dmitry Gutov @ 2020-04-26 14:34 UTC (permalink / raw)
To: Eli Zaretskii
Cc: ke.vigouroux, eggert, 40671, michael_heerdegen, mattiase, rms
On 26.04.2020 17:19, Eli Zaretskii wrote:
> Did you try compiling that as a C program, not a C++ program?
As C++.
From what I understand, in C string literals are not "const", it's just
UB to modify them.
> but even that goes away if I modify the program as follows:
>
> #include <string.h>
> int main (void) { return !strcpy ((char *)"a", "b"); }
If you go out of your way to avoid warnings, then indeed, the compiler
won't show them.
And typecasts are an easy way to turn compilation errors into runtime
errors, in general.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-26 14:34 ` Dmitry Gutov
@ 2020-04-26 15:46 ` Eli Zaretskii
2020-04-26 16:02 ` Dmitry Gutov
0 siblings, 1 reply; 170+ messages in thread
From: Eli Zaretskii @ 2020-04-26 15:46 UTC (permalink / raw)
To: Dmitry Gutov
Cc: ke.vigouroux, eggert, 40671, michael_heerdegen, mattiase, rms
> Cc: eggert@cs.ucla.edu, mattiase@acm.org, rms@gnu.org,
> michael_heerdegen@web.de, ke.vigouroux@laposte.net, 40671@debbugs.gnu.org
> From: Dmitry Gutov <dgutov@yandex.ru>
> Date: Sun, 26 Apr 2020 17:34:56 +0300
>
> > #include <string.h>
> > int main (void) { return !strcpy ((char *)"a", "b"); }
>
> If you go out of your way to avoid warnings, then indeed, the compiler
> won't show them.
>
> And typecasts are an easy way to turn compilation errors into runtime
> errors, in general.
I think this shows the difference between CANNOT and SHOULD NOT, wrt
constants.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-26 15:46 ` Eli Zaretskii
@ 2020-04-26 16:02 ` Dmitry Gutov
2020-04-26 16:58 ` Eli Zaretskii
0 siblings, 1 reply; 170+ messages in thread
From: Dmitry Gutov @ 2020-04-26 16:02 UTC (permalink / raw)
To: Eli Zaretskii
Cc: ke.vigouroux, eggert, 40671, michael_heerdegen, mattiase, rms
On 26.04.2020 18:46, Eli Zaretskii wrote:
> I think this shows the difference between CANNOT and SHOULD NOT, wrt
> constants.
I'm not sure I understand the analogy.
Anyway, C and C++ have notoriously tricky semantics in edge cases. It's
probably not a good idea to use either of them as example for Emacs Lisp.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-26 16:02 ` Dmitry Gutov
@ 2020-04-26 16:58 ` Eli Zaretskii
2020-04-26 17:39 ` Dmitry Gutov
0 siblings, 1 reply; 170+ messages in thread
From: Eli Zaretskii @ 2020-04-26 16:58 UTC (permalink / raw)
To: Dmitry Gutov
Cc: ke.vigouroux, eggert, 40671, michael_heerdegen, mattiase, rms
> Cc: ke.vigouroux@laposte.net, eggert@cs.ucla.edu, 40671@debbugs.gnu.org,
> michael_heerdegen@web.de, mattiase@acm.org, rms@gnu.org
> From: Dmitry Gutov <dgutov@yandex.ru>
> Date: Sun, 26 Apr 2020 19:02:05 +0300
>
> On 26.04.2020 18:46, Eli Zaretskii wrote:
> > I think this shows the difference between CANNOT and SHOULD NOT, wrt
> > constants.
>
> I'm not sure I understand the analogy.
That program demonstrates that in C one CAN change a "constant"
array. But one definitely SHOULD NOT do that.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-26 16:58 ` Eli Zaretskii
@ 2020-04-26 17:39 ` Dmitry Gutov
2020-04-26 18:14 ` Eli Zaretskii
0 siblings, 1 reply; 170+ messages in thread
From: Dmitry Gutov @ 2020-04-26 17:39 UTC (permalink / raw)
To: Eli Zaretskii
Cc: ke.vigouroux, eggert, 40671, michael_heerdegen, mattiase, rms
On 26.04.2020 19:58, Eli Zaretskii wrote:
> That program demonstrates that in C one CAN change a "constant"
> array.
When you first change it to a "non-constant" one, as far as the compiler
is concerned? It's an escape hatch. The same way you "can" funcall a string:
int main (void) {
return ((int(*) (int))"abc")(1);
}
It will blow up at runtime, of course.
Neither will be the case with "constant" Lisp forms we are talking
about. No runtime errors (only subtle, hard to investigate bugs from
time to time), and no compilation warnings. The only warnings at all
will be in the manual.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-26 17:39 ` Dmitry Gutov
@ 2020-04-26 18:14 ` Eli Zaretskii
2020-04-26 18:32 ` Dmitry Gutov
0 siblings, 1 reply; 170+ messages in thread
From: Eli Zaretskii @ 2020-04-26 18:14 UTC (permalink / raw)
To: Dmitry Gutov
Cc: ke.vigouroux, eggert, 40671, michael_heerdegen, mattiase, rms
> Cc: ke.vigouroux@laposte.net, eggert@cs.ucla.edu, 40671@debbugs.gnu.org,
> michael_heerdegen@web.de, mattiase@acm.org, rms@gnu.org
> From: Dmitry Gutov <dgutov@yandex.ru>
> Date: Sun, 26 Apr 2020 20:39:38 +0300
>
> int main (void) {
> return ((int(*) (int))"abc")(1);
> }
>
> It will blow up at runtime, of course.
But the previous program will not necessarily blow up at runtime.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-26 18:14 ` Eli Zaretskii
@ 2020-04-26 18:32 ` Dmitry Gutov
2020-04-26 18:41 ` Eli Zaretskii
0 siblings, 1 reply; 170+ messages in thread
From: Dmitry Gutov @ 2020-04-26 18:32 UTC (permalink / raw)
To: Eli Zaretskii
Cc: ke.vigouroux, eggert, 40671, michael_heerdegen, mattiase, rms
On 26.04.2020 21:14, Eli Zaretskii wrote:
>> Cc: ke.vigouroux@laposte.net, eggert@cs.ucla.edu, 40671@debbugs.gnu.org,
>> michael_heerdegen@web.de, mattiase@acm.org, rms@gnu.org
>> From: Dmitry Gutov <dgutov@yandex.ru>
>> Date: Sun, 26 Apr 2020 20:39:38 +0300
>>
>> int main (void) {
>> return ((int(*) (int))"abc")(1);
>> }
>>
>> It will blow up at runtime, of course.
>
> But the previous program will not necessarily blow up at runtime.
"not necessarily" is a damnably low qualifier.
My point is, that program is using the same instrument as this one,
which *will* blow up at runtime. And the instrument is "making the
compiler shut up".
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-26 18:32 ` Dmitry Gutov
@ 2020-04-26 18:41 ` Eli Zaretskii
2020-04-26 18:53 ` Dmitry Gutov
0 siblings, 1 reply; 170+ messages in thread
From: Eli Zaretskii @ 2020-04-26 18:41 UTC (permalink / raw)
To: Dmitry Gutov
Cc: ke.vigouroux, eggert, 40671, michael_heerdegen, mattiase, rms
> Cc: ke.vigouroux@laposte.net, eggert@cs.ucla.edu, 40671@debbugs.gnu.org,
> michael_heerdegen@web.de, mattiase@acm.org, rms@gnu.org
> From: Dmitry Gutov <dgutov@yandex.ru>
> Date: Sun, 26 Apr 2020 21:32:45 +0300
>
> My point is, that program is using the same instrument as this one,
> which *will* blow up at runtime.
No, it isn't the same instrument. Your program constructs a function
call using address that has no valid instructions. Paul's program
does nothing like that, it just attempts to write to a data address
which may or may not be in write-protected storage. So your program
will always blow up, whereas the other one will only blow up if the
memory is write-protected.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-26 18:41 ` Eli Zaretskii
@ 2020-04-26 18:53 ` Dmitry Gutov
0 siblings, 0 replies; 170+ messages in thread
From: Dmitry Gutov @ 2020-04-26 18:53 UTC (permalink / raw)
To: Eli Zaretskii
Cc: ke.vigouroux, eggert, 40671, michael_heerdegen, mattiase, rms
On 26.04.2020 21:41, Eli Zaretskii wrote:
>> Cc: ke.vigouroux@laposte.net, eggert@cs.ucla.edu, 40671@debbugs.gnu.org,
>> michael_heerdegen@web.de, mattiase@acm.org, rms@gnu.org
>> From: Dmitry Gutov <dgutov@yandex.ru>
>> Date: Sun, 26 Apr 2020 21:32:45 +0300
>>
>> My point is, that program is using the same instrument as this one,
>> which *will* blow up at runtime.
>
> No, it isn't the same instrument. Your program constructs a function
> call using address that has no valid instructions. Paul's program
> does nothing like that, it just attempts to write to a data address
> which may or may not be in write-protected storage. So your program
> will always blow up, whereas the other one will only blow up if the
> memory is write-protected.
I was imprecise. The program is doing a different thing.
But the programmer is using the same instrument in both cases to make it
compile.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-26 14:03 ` Dmitry Gutov
2020-04-26 14:19 ` Eli Zaretskii
@ 2020-04-26 18:57 ` Paul Eggert
2020-04-26 19:22 ` Philipp Stephani
2020-04-26 21:23 ` Dmitry Gutov
1 sibling, 2 replies; 170+ messages in thread
From: Paul Eggert @ 2020-04-26 18:57 UTC (permalink / raw)
To: Dmitry Gutov
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 4/26/20 7:03 AM, Dmitry Gutov wrote:
> g++ string_const.c++
Ah, my example was C-only. Here is an example for both C and C++:
#include <string.h>
int main (void) {
union { char const *cp; char *p; } u = { "a" };
return !strcpy (u.p, "b");
}
This has undefined behavior, and might dump core or might not depending on the
implementation. Neither gcc nor g++ issue any warnings in default compilation.
Undefined behavior is undesirable and it's not a good thing that Emacs Lisp also
has areas that behave like this. Somebody should pry free time to look into
fixing them, but that won't be trivial. It appears that portable dumping and
other changes have broken some of Emacs's runtime checking in this area.
Unfortunately, the relevant code is hairy and any fixes certainly won't happen
before the Emacs 27 release. In the meantime it's better to warn users clearly
about the gotchas in this area, to help prevent some of the confusion
exemplified by Bug#40671.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-26 18:57 ` Paul Eggert
@ 2020-04-26 19:22 ` Philipp Stephani
2020-04-26 20:14 ` Paul Eggert
2020-04-26 21:23 ` Dmitry Gutov
1 sibling, 1 reply; 170+ messages in thread
From: Philipp Stephani @ 2020-04-26 19:22 UTC (permalink / raw)
To: Paul Eggert
Cc: ke.vigouroux, 40671, Michael Heerdegen, Mattias Engdegård,
Dmitry Gutov, Richard Stallman
Am So., 26. Apr. 2020 um 20:58 Uhr schrieb Paul Eggert <eggert@cs.ucla.edu>:
>
> On 4/26/20 7:03 AM, Dmitry Gutov wrote:
> > g++ string_const.c++
>
> Ah, my example was C-only. Here is an example for both C and C++:
>
> #include <string.h>
> int main (void) {
> union { char const *cp; char *p; } u = { "a" };
> return !strcpy (u.p, "b");
> }
>
> This has undefined behavior, and might dump core or might not depending on the
> implementation. Neither gcc nor g++ issue any warnings in default compilation.
Yes, but nobody "accidentally" writes code like this. OTOH, code like
attempting to mutate a "constant" Lisp object seems trivial to write
accidentally.
>
> Undefined behavior is undesirable and it's not a good thing that Emacs Lisp also
> has areas that behave like this. Somebody should pry free time to look into
> fixing them, but that won't be trivial.
What would be needed? We could either (a) remove the notion of
"constant" objects so that all objects become mutable, (b) introduce
static type checking including const-correctness so that attempting to
mutate a "constant" object would fail byte-compilation, and/or (c)
make it an error to mutate such objects at runtime (similar to (set t
nil)).
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-26 19:22 ` Philipp Stephani
@ 2020-04-26 20:14 ` Paul Eggert
0 siblings, 0 replies; 170+ messages in thread
From: Paul Eggert @ 2020-04-26 20:14 UTC (permalink / raw)
To: Philipp Stephani
Cc: ke.vigouroux, 40671, Michael Heerdegen, Mattias Engdegård,
Dmitry Gutov, Richard Stallman
On 4/26/20 12:22 PM, Philipp Stephani wrote:
> nobody "accidentally" writes code like this.
Not code like my trivial example, no. But the underlying problem is all too
common. After all, it's why Emacs is dumping core here - the Emacs Lisp
interpreter is using C code like that to implement some Lisp strings.
> We could either (a) remove the notion of
> "constant" objects so that all objects become mutable, (b) introduce
> static type checking including const-correctness so that attempting to
> mutate a "constant" object would fail byte-compilation, and/or (c)
> make it an error to mutate such objects at runtime (similar to (set t
> nil)).
Neither (a) nor (b) sound very practical. Emacs formerly did a better job at (c)
and could do so again, so it's an obvious way to move forward here.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-26 18:57 ` Paul Eggert
2020-04-26 19:22 ` Philipp Stephani
@ 2020-04-26 21:23 ` Dmitry Gutov
2020-04-26 23:13 ` Paul Eggert
1 sibling, 1 reply; 170+ messages in thread
From: Dmitry Gutov @ 2020-04-26 21:23 UTC (permalink / raw)
To: Paul Eggert
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 26.04.2020 21:57, Paul Eggert wrote:
> On 4/26/20 7:03 AM, Dmitry Gutov wrote:
>> g++ string_const.c++
>
> Ah, my example was C-only. Here is an example for both C and C++:
>
> #include <string.h>
> int main (void) {
> union { char const *cp; char *p; } u = { "a" };
> return !strcpy (u.p, "b");
> }
>
> This has undefined behavior, and might dump core or might not depending on the
> implementation. Neither gcc nor g++ issue any warnings in default compilation.
This just illustrates a weakness of type system in C/C++. The same way
you could pass a string into a function that expects an int.
> Undefined behavior is undesirable and it's not a good thing that Emacs Lisp also
> has areas that behave like this.
But is it undefined? I think it's well-defined and predictable, though
it's harder to make sense of that we would like.
> Somebody should pry free time to look into
> fixing them, but that won't be trivial. It appears that portable dumping and
> other changes have broken some of Emacs's runtime checking in this area.
Do you have an example of a version of Emacs where this behavior was
different?
> Unfortunately, the relevant code is hairy and any fixes certainly won't happen
> before the Emacs 27 release. In the meantime it's better to warn users clearly
> about the gotchas in this area, to help prevent some of the confusion
> exemplified by Bug#40671.
Perhaps you meant some other bug report? This is the one we're
commenting on.
My concern here is the terms. I worry that someday someone will come
report a problem, and we respond with "this syntax creates constant
values, please take care not to modify them". Then that someone will go
away with very low opinion of our mental faculties.
In all of my experience, the term "constant" is usually applied to names
(variables), or pointers. And it almost always means that you're not
allowed to change it. Or if you are, you can't do it by accident.
The closest term that applies to values, I think, is "immutable". But
those are definitely protected from modification.
For our situation, the term "constant reference" comes to mind, but I
don't know exactly how to rephrase the manual best.
The previous term "literal objects", however, seems accurate enough, and
if the "constant-ness" is going to live only in the manual anyway,
perhaps we should just say "please don't modify literal objects [unless
you really know what you're doing]".
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-26 21:23 ` Dmitry Gutov
@ 2020-04-26 23:13 ` Paul Eggert
2020-04-27 0:53 ` Dmitry Gutov
0 siblings, 1 reply; 170+ messages in thread
From: Paul Eggert @ 2020-04-26 23:13 UTC (permalink / raw)
To: Dmitry Gutov
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 4/26/20 2:23 PM, Dmitry Gutov wrote:
> This just illustrates a weakness of type system in C/C++. The same way you could
> pass a string into a function that expects an int.
Although it's a weakness, it's different from the char * vs int weakness. It's
well-defined in C that one can cast char * to char const * and back without
trouble. The same is not true for casting char * to int and back.
> is it undefined?
Yes, it's undefined. C11 section 6.7.3 paragraph 6 says, "If an attempt is made
to modify an object defined with a const-qualified type through use of an lvalue
with non-const-qualified type, the behavior is undefined."
> Do you have an example of a version of Emacs where this behavior was different?
Emacs 26.
>> Unfortunately, the relevant code is hairy and any fixes certainly won't happen
>> before the Emacs 27 release. In the meantime it's better to warn users clearly
>> about the gotchas in this area, to help prevent some of the confusion
>> exemplified by Bug#40671.
>
> Perhaps you meant some other bug report?
No, the original bug report that started this thread illustrates some of the
confusion in this area.
> In all of my experience, the term "constant" is usually applied to names
> (variables), or pointers. And it almost always means that you're not allowed to
> change it. Or if you are, you can't do it by accident.
Unfortunately that experience does not apply to C and to other low-level
languages. Even Java once allowed programs to modify "constants" by using
reflection, though recent Java versions have fixed this.
> The previous term "literal objects", however, seems accurate enough
We could use any term we like, and if there's consensus for using the term
"literal object" instead of "constant" then we can redo the manual that way.
However, the problem can occur with strings that were never string literals in
any source-code Elisp program. And a Elisp string can begin its life as a
mutable string and then become a "constant" (or "literal object") later. So it's
not clear that the longer phrase is less confusing.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-26 23:13 ` Paul Eggert
@ 2020-04-27 0:53 ` Dmitry Gutov
2020-04-27 1:49 ` Paul Eggert
0 siblings, 1 reply; 170+ messages in thread
From: Dmitry Gutov @ 2020-04-27 0:53 UTC (permalink / raw)
To: Paul Eggert
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 27.04.2020 02:13, Paul Eggert wrote:
>> This just illustrates a weakness of type system in C/C++. The same way you could
>> pass a string into a function that expects an int.
>
> Although it's a weakness, it's different from the char * vs int weakness. It's
> well-defined in C that one can cast char * to char const * and back without
> trouble. The same is not true for casting char * to int and back.
This compiles fine:
#include <string.h>
int main (void) { return !strcpy ((char*)2, "b"); }
My point is, it's hard to discuss static typing guarantees when type
casting is involved.
>> is it undefined?
>
> Yes, it's undefined. C11 section 6.7.3 paragraph 6 says, "If an attempt is made
> to modify an object defined with a const-qualified type through use of an lvalue
> with non-const-qualified type, the behavior is undefined."
Sorry if that was unclear. I mean, is the behavior of "literal objects"
in Emacs Lisp undefined when one tries to modify them?
>> Do you have an example of a version of Emacs where this behavior was different?
>
> Emacs 26.
Sorry, I don't have an Emacs 26 at hand. Should 25 suffice? Just tried
this in IELM:
ELISP> (setq a '(1 . 2))
(1 . 2)
ELISP> (setcdr a 3)
3 (#o3, #x3, ?\C-c)
ELISP> a
(1 . 3)
ELISP> emacs-version
"25.2.3"
>>> Unfortunately, the relevant code is hairy and any fixes certainly won't happen
>>> before the Emacs 27 release. In the meantime it's better to warn users clearly
>>> about the gotchas in this area, to help prevent some of the confusion
>>> exemplified by Bug#40671.
>>
>> Perhaps you meant some other bug report?
>
> No, the original bug report that started this thread illustrates some of the
> confusion in this area.
Okay, yes. I though you had a bug report with a description of a
practical problem.
>> In all of my experience, the term "constant" is usually applied to names
>> (variables), or pointers. And it almost always means that you're not allowed to
>> change it. Or if you are, you can't do it by accident.
>
> Unfortunately that experience does not apply to C and to other low-level
> languages. Even Java once allowed programs to modify "constants" by using
> reflection, though recent Java versions have fixed this.
Hence the last sentence of my paragraph you quoted.
In Ruby, we also have "constants" and we sometimes laugh about being
able to change them. And yet, there also you can't do it by accident.
>> The previous term "literal objects", however, seems accurate enough
>
> We could use any term we like, and if there's consensus for using the term
> "literal object" instead of "constant" then we can redo the manual that way.
> However, the problem can occur with strings that were never string literals in
> any source-code Elisp program. And a Elisp string can begin its life as a
> mutable string and then become a "constant" (or "literal object") later. So it's
> not clear that the longer phrase is less confusing.
"A mutable string can become a constant later and yet remain modifiable
in practice" sounds really confusing.
We better warn against modifying any values that are part of a "literal
object" anywhere.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-27 0:53 ` Dmitry Gutov
@ 2020-04-27 1:49 ` Paul Eggert
2020-04-28 3:05 ` Dmitry Gutov
0 siblings, 1 reply; 170+ messages in thread
From: Paul Eggert @ 2020-04-27 1:49 UTC (permalink / raw)
To: Dmitry Gutov
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 4/26/20 5:53 PM, Dmitry Gutov wrote:
> is the behavior of "literal objects" in Emacs
> Lisp undefined when one tries to modify them?
Yes.
>>> Do you have an example of a version of Emacs where this behavior was different?
>>
>> Emacs 26.
>
> Sorry, I don't have an Emacs 26 at hand. Should 25 suffice?
Yes.
Just tried this in
> IELM:
>
> ELISP> (setq a '(1 . 2))
> (1 . 2)
>
> ELISP> (setcdr a 3)
> 3 (#o3, #x3, ?\C-c)
> ELISP> a
> (1 . 3)
Yes, the behavior is undefined in Emacs 25 too. Undefined means that the
behavior you describe is allowed - in this instance you modified the "constant"
and got away with it.
> In Ruby, we also have "constants" and we sometimes laugh about being able to
> change them. And yet, there also you can't do it by accident.
I suppose it depends on what one means by "accident". :-) Perhaps we could agree
that accidents, whatever they are, happen more often in C....
> We better warn against modifying any values that are part of a "literal object"
> anywhere.
That's what the emacs-27 doc does, or at least tries to do.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-27 1:49 ` Paul Eggert
@ 2020-04-28 3:05 ` Dmitry Gutov
2020-04-28 8:17 ` Paul Eggert
0 siblings, 1 reply; 170+ messages in thread
From: Dmitry Gutov @ 2020-04-28 3:05 UTC (permalink / raw)
To: Paul Eggert
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 27.04.2020 04:49, Paul Eggert wrote:
>> Sorry, I don't have an Emacs 26 at hand. Should 25 suffice?
>
> Yes.
>
> Just tried this in
>> IELM:
>>
>> ELISP> (setq a '(1 . 2))
>> (1 . 2)
>>
>> ELISP> (setcdr a 3)
>> 3 (#o3, #x3, ?\C-c)
>> ELISP> a
>> (1 . 3)
>
> Yes, the behavior is undefined in Emacs 25 too. Undefined means that the
> behavior you describe is allowed - in this instance you modified the "constant"
> and got away with it.
I'm not sure which problematic cases you mean, then. Ones related to
pure space?
>> In Ruby, we also have "constants" and we sometimes laugh about being able to
>> change them. And yet, there also you can't do it by accident.
>
> I suppose it depends on what one means by "accident". :-) Perhaps we could agree
> that accidents, whatever they are, happen more often in C....
It feels like you're just side-stepping the arguments, one after another.
>> We better warn against modifying any values that are part of a "literal object"
>> anywhere.
>
> That's what the emacs-27 doc does, or at least tries to do.
I wish it did that without inventing new meanings for the words
"constant" and "mutable". It will only breed confusion.
Take this paragraph:
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}.
It makes one think that 'aset' can't be called on "aaa". That it will
either fail to change the value, or signal an error. Whereas the result
is that the value is changed, no errors or warnings.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-28 3:05 ` Dmitry Gutov
@ 2020-04-28 8:17 ` Paul Eggert
2020-04-28 13:54 ` Dmitry Gutov
2020-04-28 17:25 ` Drew Adams
0 siblings, 2 replies; 170+ messages in thread
From: Paul Eggert @ 2020-04-28 8:17 UTC (permalink / raw)
To: Dmitry Gutov
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 4/27/20 8:05 PM, Dmitry Gutov wrote:
> I'm not sure which problematic cases you mean, then. Ones related to pure space?
That's one issue. Earlier versions of Emacs also had trouble if you modified
list structures while executing them. I've squashed some of those issues more
recently but would not be surprised if some remain.
I don't know how much optimization the byte compiler did in earlier versions,
but if it did anything like what it does now, that's also a source of problems.
> 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}.
>
> It makes one think that 'aset' can't be called on "aaa". That it will either
> fail to change the value, or signal an error. Whereas the result is that the
> value is changed, no errors or warnings.
'aset' *shouldn't* be called on "aaa".
We could replace "a constant string" with "a constant string that should not be
changed"; would that help?
> It feels like you're just side-stepping the arguments, one after another.
There's certainly no intent to side-step. And I don't sense that there's really
much disagreement here: we both agree that the current behavior is unfortunate,
the major point of disagreement is about terminology in the documentation.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-28 8:17 ` Paul Eggert
@ 2020-04-28 13:54 ` Dmitry Gutov
2020-04-28 17:59 ` Paul Eggert
2020-04-28 17:25 ` Drew Adams
1 sibling, 1 reply; 170+ messages in thread
From: Dmitry Gutov @ 2020-04-28 13:54 UTC (permalink / raw)
To: Paul Eggert
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 28.04.2020 11:17, Paul Eggert wrote:
> On 4/27/20 8:05 PM, Dmitry Gutov wrote:
>
>> I'm not sure which problematic cases you mean, then. Ones related to pure space?
>
> That's one issue. Earlier versions of Emacs also had trouble if you modified
> list structures while executing them. I've squashed some of those issues more
> recently but would not be surprised if some remain.
If any led to segfaults, they have to be fixed in the code anyway.
> I don't know how much optimization the byte compiler did in earlier versions,
> but if it did anything like what it does now, that's also a source of problems.
Well, here's a damning example. And it doesn't involve the byte compiler:
ELISP> (defun abc () "abc")
abc
ELISP> (aset (abc) 0 ?b)
98 (#o142, #x62, ?b)
ELISP> (abc)
"bbc"
I wonder how other Lisps deal with that.
The Ruby interpreter, from the first release I think, always created
copies of the literals when a method was called. Exactly to avoid this
kind of broken semantics.
In the recent versions, they added a pragma string (to be added to the
top of the file) that makes all such literals in that file "immutable".
That means that any attempt to change them errors at runtime. And now
it's considered good style to use that pragma everywhere.
>> 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}.
>>
>> It makes one think that 'aset' can't be called on "aaa". That it will either
>> fail to change the value, or signal an error. Whereas the result is that the
>> value is changed, no errors or warnings.
>
> 'aset' *shouldn't* be called on "aaa".
Indeed it shouldn't.
> We could replace "a constant string" with "a constant string that should not be
> changed"; would that help?
That sounds like a weird tautological non-advice.
It shouldn't be changed because it's a value of a string literal. Not
because it's constant (it isn't).
>> It feels like you're just side-stepping the arguments, one after another.
>
> There's certainly no intent to side-step. And I don't sense that there's really
> much disagreement here: we both agree that the current behavior is unfortunate,
> the major point of disagreement is about terminology in the documentation.
From the outset all arguments were about the terminology.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-28 8:17 ` Paul Eggert
2020-04-28 13:54 ` Dmitry Gutov
@ 2020-04-28 17:25 ` Drew Adams
2020-04-28 17:47 ` Paul Eggert
1 sibling, 1 reply; 170+ messages in thread
From: Drew Adams @ 2020-04-28 17:25 UTC (permalink / raw)
To: Paul Eggert, Dmitry Gutov
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
> There's certainly no intent to side-step.
> And I don't sense that there's really
> much disagreement here: we both agree that
> the current behavior is unfortunate,
> the major point of disagreement is about
> terminology in the documentation.
Has anyone agreed with you here about your use
of "cannot" instead of "should not" and your
unconventional use of "constant"/"immutable"
and "mutable"?
I don't think I've seen any support for that
here (did I just miss it?). Still you persist.
I don't really see the doc/message for users
getting clearer; it seems like the waters are
being muddied.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-28 17:25 ` Drew Adams
@ 2020-04-28 17:47 ` Paul Eggert
2020-04-29 0:32 ` Michael Heerdegen
0 siblings, 1 reply; 170+ messages in thread
From: Paul Eggert @ 2020-04-28 17:47 UTC (permalink / raw)
To: Drew Adams, Dmitry Gutov
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 4/28/20 10:25 AM, Drew Adams wrote:
> Has anyone agreed with you
Nobody's happy with the current documentation's language (not even me), but
nobody has proposed specific wording improvements either. That's what committees
do sometimes; we might not agree, but the guy who does most of the work
generates something that nobody has the time to improve significantly.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-28 13:54 ` Dmitry Gutov
@ 2020-04-28 17:59 ` Paul Eggert
2020-04-28 18:46 ` Dmitry Gutov
0 siblings, 1 reply; 170+ messages in thread
From: Paul Eggert @ 2020-04-28 17:59 UTC (permalink / raw)
To: Dmitry Gutov
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 4/28/20 6:54 AM, Dmitry Gutov wrote:
> It shouldn't be changed because it's a value of a string literal. Not because
> it's constant (it isn't).
That depends on the string literal and the particular Emacs implementation. In
Emacs master, some string literals yield strings that are constant because Emacs
has undefined behavior at the C level (maybe coredump, maybe not) if you try to
change them, some string literals are constant because if you try to change them
Emacs will reliably signal an error, some string literals are constant because
if you change them Emacs might behave unpredictably without having undefined
behavior at the C level, and the remaining string literals are constant becase
you shouldn't change them. We have never documented exactly which string
literals are which, and we shouldn't document that now because it is an
implementation detail that users should not rely upon.
It would be a mistake for the documentation to say that the problems we've been
discussing occur only with string literals, as these problems can occur for
strings that were not generated from string literals, and they can also occur
for objects that are not strings. So "string literal" would be the wrong
terminology here.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-28 17:59 ` Paul Eggert
@ 2020-04-28 18:46 ` Dmitry Gutov
2020-04-28 19:20 ` Paul Eggert
0 siblings, 1 reply; 170+ messages in thread
From: Dmitry Gutov @ 2020-04-28 18:46 UTC (permalink / raw)
To: Paul Eggert
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 28.04.2020 20:59, Paul Eggert wrote:
> On 4/28/20 6:54 AM, Dmitry Gutov wrote:
>> It shouldn't be changed because it's a value of a string literal. Not because
>> it's constant (it isn't).
>
> That depends on the string literal and the particular Emacs implementation. In
> Emacs master, some string literals yield strings that are constant because Emacs
> has undefined behavior at the C level (maybe coredump, maybe not)
That sounds like something we have to fix. Emacs shouldn't dump core no
matter what Lisp code the user wrote. Unless it leads to an OOM, I guess.
> if you try to
> change them, some string literals are constant because if you try to change them
> Emacs will reliably signal an error, some string literals are constant because
> if you change them Emacs might behave unpredictably without having undefined
> behavior at the C level, and the remaining string literals are constant becase
> you shouldn't change them.
That's not a constant, that's an eldritch abomination. Some unknown,
unpredictable thing. Which is generally bad for language semantics and
for its users. I understand why it's hard to fix that, but co-opting
common words to mean different things is bad. Using semantics that might
be "slightly familiar" only to grizzled C programmers is also bad.
If you really want to have an adjective for such values, either ask some
language theorist or make up one (and I'm only half-kidding here).
Example: Some values in Emacs are constant, meaning you can't change
them (e.g. you can't change an integer), and some are mutable (e.g. a
cons cell is easy to change). There is a particular kind of values
called fizzleworp (see {String literals}, {Quote} and {Backquote}),
which are dangerous to modify. Please take care not to do that in your code.
<... some enumeration of situation which create fizzleworp values or
make an existing value fizzleworp ...>
OR
Anyplace we introduce literals in the manual, if they are dangerous to
modify, we say that. Without inventing new words.
> We have never documented exactly which string
> literals are which, and we shouldn't document that now because it is an
> implementation detail that users should not rely upon.
No argument here.
> It would be a mistake for the documentation to say that the problems we've been
> discussing occur only with string literals, as these problems can occur for
> strings that were not generated from string literals, and they can also occur
> for objects that are not strings. So "string literal" would be the wrong
> terminology here.
String literals, Lisp form literals, and any members of such forms. I
might be forgetting something, but this list is not too long, is it?
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-28 18:46 ` Dmitry Gutov
@ 2020-04-28 19:20 ` Paul Eggert
2020-04-28 19:33 ` Dmitry Gutov
0 siblings, 1 reply; 170+ messages in thread
From: Paul Eggert @ 2020-04-28 19:20 UTC (permalink / raw)
To: Dmitry Gutov
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 4/28/20 11:46 AM, Dmitry Gutov wrote:
> That sounds like something we have to fix.
Yes, absolutely, though we can't feasibly do that before the next release.
> That's not a constant, that's an eldritch abomination.
I say "constant", you say "eldritch". :-)
> Using semantics that might be "slightly familiar"
> only to grizzled C programmers is also bad.
It's not just "slightly familiar" to grizzled C/C++/etc. programmers. It's a
concept that's pretty much part of their daily lives.
> There is a particular kind of values called fizzleworp (see {String literals}, {Quote} and {Backquote}), which are dangerous to modify.
Let's not go that route. It'd be overdocumenting internal details that are not
generally known. I don't know all the details, so I couldn't write all that
documentation without a lot of nontrivial investigation. And these details are
likely to change so users should not rely on them anyway.
Instead of going out into the wilderness and tagging and identifying each dragon
and its lair, the documentation should keep things simple and merely say "there
are dragons out in the wilderness; you shouldn't go there". This is much simpler
and easier to understand and maintain, and is safer overall.
> Lisp form literals, and any members of such forms. I might be forgetting something, but this list is not too long, is it?
Yes the list isn't *that* long, and it's in the documentation already - as long
as we are willing to put up with a conservative list (e.g., you shouldn't modify
anything in the list) rather than insisting on an exhaustive list (e.g., here's
what happens if you try to modify X, here's what happens if you try to modify Y,
etc.).
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-28 19:20 ` Paul Eggert
@ 2020-04-28 19:33 ` Dmitry Gutov
2020-04-28 20:09 ` Paul Eggert
0 siblings, 1 reply; 170+ messages in thread
From: Dmitry Gutov @ 2020-04-28 19:33 UTC (permalink / raw)
To: Paul Eggert
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 28.04.2020 22:20, Paul Eggert wrote:
> On 4/28/20 11:46 AM, Dmitry Gutov wrote:
>
>> That sounds like something we have to fix.
>
> Yes, absolutely, though we can't feasibly do that before the next release.
Yeah, ok.
>> That's not a constant, that's an eldritch abomination.
>
> I say "constant", you say "eldritch". :-)
And then I explain why "constant" is bad, multiple times. With examples
from other languages.
>> Using semantics that might be "slightly familiar"
>> only to grizzled C programmers is also bad.
>
> It's not just "slightly familiar" to grizzled C/C++/etc. programmers. It's a
> concept that's pretty much part of their daily lives.
You take the concept of "constant values", look it up in the C standard
(where modifying a constant is "undefined behavior") and then make a
conclusion that if modifying something is "undefined behavior", it must
be called a constant. Outside of C standard, to boot.
Emacs users are not C programmers.
>> There is a particular kind of values called fizzleworp (see {String literals}, {Quote} and {Backquote}), which are dangerous to modify.
>
> Let's not go that route. It'd be overdocumenting internal details that are not
> generally known. I don't know all the details, so I couldn't write all that
> documentation without a lot of nontrivial investigation. And these details are
> likely to change so users should not rely on them anyway.
That's not what I was suggesting. I gave an example on using the words,
not on which cases to enumerate.
> Instead of going out into the wilderness and tagging and identifying each dragon
> and its lair, the documentation should keep things simple and merely say "there
> are dragons out in the wilderness; you shouldn't go there". This is much simpler
> and easier to understand and maintain, and is safer overall.
The map still has to circle the wilderness on the map somehow.
>> Lisp form literals, and any members of such forms. I might be forgetting something, but this list is not too long, is it?
>
> Yes the list isn't *that* long, and it's in the documentation already - as long
> as we are willing to put up with a conservative list (e.g., you shouldn't modify
> anything in the list) rather than insisting on an exhaustive list (e.g., here's
> what happens if you try to modify X, here's what happens if you try to modify Y,
> etc.).
Conservative list is fine, as long as we don't use the word "constant".
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-28 19:33 ` Dmitry Gutov
@ 2020-04-28 20:09 ` Paul Eggert
2020-04-28 21:10 ` Dmitry Gutov
2020-04-28 21:18 ` Dmitry Gutov
0 siblings, 2 replies; 170+ messages in thread
From: Paul Eggert @ 2020-04-28 20:09 UTC (permalink / raw)
To: Dmitry Gutov
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 4/28/20 12:33 PM, Dmitry Gutov wrote:
> And then I explain why "constant" is bad, multiple times. With examples from
> other languages.
The word "constant" means different things in different programming languages.
The meaning used in the Elisp manual is reasonably close to its meaning in
C/C++/Fortran/Common Lisp/etc., and that describes how Emacs behaves now. We'd
prefer it if Emacs behaved more like what Python does with its immutable
objects, and some day we should change Emacs to do that. When we do so, we can
modify the Elisp manual accordingly. In the meantime we need to document what we
have.
> Emacs users are not C programmers.
Of course not, but this area needs documentation and when the Emacs concept is
similar to an already-existing one in C/C++/etc. it's not necessarily a bad
thing to adopt their terminology and/or notation, even if that
terminology/notation happens to mean something else in other contexts.
>>> There is a particular kind of values called fizzleworp (see {String
>>> literals}, {Quote} and {Backquote}), which are dangerous to modify.
>>
>> Let's not go that route. It'd be overdocumenting internal details that are not
>> generally known. I don't know all the details, so I couldn't write all that
>> documentation without a lot of nontrivial investigation. And these details are
>> likely to change so users should not rely on them anyway.
>
> That's not what I was suggesting. I gave an example on using the words, not on
> which cases to enumerate.
Then I don't understand your suggestion.
I thought you were saying that we should distinguish among the types of
constants and should say what happens when you modify each type. The manual
already does this to a very limited extent, and I thought you were suggesting
that it should do a reasonably exhaustive job of it, in order to greatly limit
the area where Emacs behavior is undefined.
I'd rather not go that route generally, for the reasons stated above. That being
said, it might make sense to make some changes in this area. Or perhaps I'm
still misunderstanding you, in which case further clarification would be helpful.
A simple way to be clear in this area is to propose specific wording changes,
preferably in git format-patch form. It's not enough to say "I don't like the
word 'constant'."
> The map still has to circle the wilderness on the map somehow.
Yes, and the documentation does that now. The edge of the wild is the line
between constants and non-constants. A program that tries to modify a constant
is out in the wilderness.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-28 20:09 ` Paul Eggert
@ 2020-04-28 21:10 ` Dmitry Gutov
2020-04-28 23:10 ` Paul Eggert
2020-04-28 21:18 ` Dmitry Gutov
1 sibling, 1 reply; 170+ messages in thread
From: Dmitry Gutov @ 2020-04-28 21:10 UTC (permalink / raw)
To: Paul Eggert
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 28.04.2020 23:09, Paul Eggert wrote:
> The word "constant" means different things in different programming languages.
> The meaning used in the Elisp manual is reasonably close to its meaning in
> C/C++/Fortran/Common Lisp/etc., and that describes how Emacs behaves now.
As we've pointed out, Elisp is a wildly different beast from C. Static
vs. dynamic, etcetera.
> Of course not, but this area needs documentation and when the Emacs concept is
> similar to an already-existing one in C/C++/etc.
Not really.
> Then I don't understand your suggestion.
>
> I thought you were saying that we should distinguish among the types of
> constants and should say what happens when you modify each type.
Which part of my example contained the "what happens when"?
> A simple way to be clear in this area is to propose specific wording changes,
> preferably in git format-patch form. It's not enough to say "I don't like the
> word 'constant'."
Could you first provide the list of your commits that changed the manual
pertaining to this discussion?
Then I'll at least know what to try to change.
> Yes, and the documentation does that now. The edge of the wild is the line
> between constants and non-constants.
Write that line between fizzleworp and non-fizzleworp values.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-28 20:09 ` Paul Eggert
2020-04-28 21:10 ` Dmitry Gutov
@ 2020-04-28 21:18 ` Dmitry Gutov
1 sibling, 0 replies; 170+ messages in thread
From: Dmitry Gutov @ 2020-04-28 21:18 UTC (permalink / raw)
To: Paul Eggert
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 28.04.2020 23:09, Paul Eggert wrote:
> I thought you were saying that we should distinguish among the types of
> constants
Among the types of mutable values. Between the "normal" and "do not
touch" ones.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-28 21:10 ` Dmitry Gutov
@ 2020-04-28 23:10 ` Paul Eggert
2020-04-28 23:36 ` Dmitry Gutov
` (2 more replies)
0 siblings, 3 replies; 170+ messages in thread
From: Paul Eggert @ 2020-04-28 23:10 UTC (permalink / raw)
To: Dmitry Gutov
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 4/28/20 2:10 PM, Dmitry Gutov wrote:
> On 28.04.2020 23:09, Paul Eggert wrote:
>> The meaning used in the Elisp manual is reasonably close to its meaning in
>> C/C++/Fortran/Common Lisp/etc., and that describes how Emacs behaves now.
>
> As we've pointed out, Elisp is a wildly different beast from C.
And Elisp is also wildly different from Common Lisp, for some interpretation of
"wildly different". But it's close enough in this area. I don't see why we
should depart from terminology used by C/C++/Fortran/Common Lisp/etc.; it's
reasonably well-established.
>> I thought you were saying that we should distinguish among the types of
>> constants and should say what happens when you modify each type.
> Among the types of mutable values. Between the "normal" and "do not touch" ones.
The "do not touch" values are called "constants" in the documentation now, just
as they are in the documentation for the other languages. I don't see why values
that should not change should be called "mutable".
And even if we called these values "mutable", I don't see why the documentation
should distinguish among the various types of "mutable" values that should not
change. The whole area is messy and differs from release to release and from
platform to platform. Programs should not change values-that-should-not-change
and we shouldn't try to catalog what happens if programs do what they shouldn't,
since it's complicated and we often don't even know what'll happen.
Generally speaking, the Elisp documentation should just say "you shouldn't
change these objects", like it does for C/C++/etc.
> Could you first provide the list of your commits that changed the manual
> pertaining to this discussion?
You can run this shell command in the emacs-27 branch.
git log --author=eggert --since='Apr 18 12:59:17 2020 -0700'
> Write that line between fizzleworp and non-fizzleworp values.
I don't understand this remark.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-28 23:10 ` Paul Eggert
@ 2020-04-28 23:36 ` Dmitry Gutov
2020-04-28 23:53 ` Paul Eggert
2020-04-28 23:53 ` Dmitry Gutov
2020-04-29 0:55 ` Drew Adams
2 siblings, 1 reply; 170+ messages in thread
From: Dmitry Gutov @ 2020-04-28 23:36 UTC (permalink / raw)
To: Paul Eggert
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 29.04.2020 02:10, Paul Eggert wrote:
> The "do not touch" values are called "constants" in the documentation now, just
> as they are in the documentation for the other languages.
In other languages, constants are something you can't change.
> I don't see why values
> that should not change should be called "mutable".
Mutable values are ones the user _can_ change. It's a structural thing.
> And even if we called these values "mutable", I don't see why the documentation
> should distinguish among the various types of "mutable" values that should not
> change.
Because the user sees strings and conses in both cases. All mutable
values, and yet changing some of them is a bad idea (even though Emacs
will most likely let you).
> Generally speaking, the Elisp documentation should just say "you shouldn't
> change these objects", like it does for C/C++/etc.
Do you see me arguing against that?
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-25 2:22 ` Paul Eggert
2020-04-25 6:00 ` Andreas Schwab
@ 2020-04-28 23:52 ` Michael Heerdegen
1 sibling, 0 replies; 170+ messages in thread
From: Michael Heerdegen @ 2020-04-28 23:52 UTC (permalink / raw)
To: Paul Eggert; +Cc: Mattias Engdegård, 40671, ke.vigouroux
Paul Eggert <eggert@cs.ucla.edu> writes:
> > (let ((l (list 1 2 3)))
> > (funcall (lambda () l)))
> >
> > Has the list become a constant?
>
> No, because the list is not part of the expression that is being evaluated.
> However, something like this could cause trouble:
>
> (let ((l (list 'lambda '(x) '(setcdr l x))))
> (eval (list l l)))
FWIW, I asked also because `funcall' seems, at least AFAIU, share some
code with `eval', and with lexical-binding on the lambda gets
transformed into something that does include the original list, so the
list becomes part of the evaluated expression.
Michael.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-28 23:10 ` Paul Eggert
2020-04-28 23:36 ` Dmitry Gutov
@ 2020-04-28 23:53 ` Dmitry Gutov
2020-04-29 0:04 ` Paul Eggert
2020-04-29 0:55 ` Drew Adams
2 siblings, 1 reply; 170+ messages in thread
From: Dmitry Gutov @ 2020-04-28 23:53 UTC (permalink / raw)
To: Paul Eggert
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 29.04.2020 02:10, Paul Eggert wrote:
> terminology used by C/C++/Fortran
Quote from https://en.cppreference.com/w/cpp/language/cv:
const object - an object whose type is const-qualified, or a non-mutable
subobject of a const object. Such object _cannot_ be modified: attempt
to do so directly is a _compile-time error_, and attempt to do so
indirectly (e.g., by modifying the const object through a reference or
pointer to non-const type) results in undefined behavior.
Emphasis mine.
I'll take a look at the commit, thanks.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-28 23:36 ` Dmitry Gutov
@ 2020-04-28 23:53 ` Paul Eggert
2020-04-28 23:57 ` Dmitry Gutov
0 siblings, 1 reply; 170+ messages in thread
From: Paul Eggert @ 2020-04-28 23:53 UTC (permalink / raw)
To: Dmitry Gutov
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 4/28/20 4:36 PM, Dmitry Gutov wrote:
> On 29.04.2020 02:10, Paul Eggert wrote:
>> The "do not touch" values are called "constants" in the documentation now, just
>> as they are in the documentation for the other languages.
>
> In other languages, constants are something you can't change.
That's not true for C, or for Common Lisp, or for the other languages I
mentioned. You can change constants sometimes and not others. Behavior is
undefined if you try.
It sounds like we're merely disagreeing about using the word "constant" vs using
some other word or phrase (it's not clear what). But there's clear precedent
elsewhere for the terminology now in use in the emacs-27 manual.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-28 23:53 ` Paul Eggert
@ 2020-04-28 23:57 ` Dmitry Gutov
0 siblings, 0 replies; 170+ messages in thread
From: Dmitry Gutov @ 2020-04-28 23:57 UTC (permalink / raw)
To: Paul Eggert
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 29.04.2020 02:53, Paul Eggert wrote:
> It sounds like we're merely disagreeing about using the word "constant" vs using
> some other word or phrase (it's not clear what).
I gave a couple of options.
> But there's clear precedent
> elsewhere for the terminology now in use in the emacs-27 manual.
Any particular example? Before your latest changes, I mean.
Please don't say 'defconst'.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-28 23:53 ` Dmitry Gutov
@ 2020-04-29 0:04 ` Paul Eggert
2020-04-29 0:14 ` Dmitry Gutov
0 siblings, 1 reply; 170+ messages in thread
From: Paul Eggert @ 2020-04-29 0:04 UTC (permalink / raw)
To: Dmitry Gutov
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 4/28/20 4:53 PM, Dmitry Gutov wrote:
> const object - an object whose type is const-qualified, or a non-mutable
> subobject of a const object. Such object _cannot_ be modified: attempt to do so
> directly is a _compile-time error_, and attempt to do so indirectly (e.g., by
> modifying the const object through a reference or pointer to non-const type)
> results in undefined behavior.
It's reasonable to have compile-time checking in a statically-typed language,
though (as the above quote notes) the checking isn't adequate for C++ and one
can get undefined behavior anyway in that language. And we could add some
similar compile-time checking for the Elisp byte-compiler: it could warn about
misuses like (aset "abc" 0 ?d), for example.
However, any such compile-time checking would be either too restrictive (with
false positives) or only partial (with false negatives) or both (as in C++). So
it wouldn't be an adequate substitute for documenting that some objects should
not be changed.
> I gave a couple of options.
I recall your using "literal object" but that's not a good choice of wording
because the problem can occur with objects that are not literally present in any
source code.
>> there's clear precedent
>> elsewhere for the terminology now in use in the emacs-27 manual.
>
> Any particular example?
By "elsewhere" I meant in other language documentation (C/C++/etc.), not
elsewhere in the emacs-27 manual.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-29 0:04 ` Paul Eggert
@ 2020-04-29 0:14 ` Dmitry Gutov
0 siblings, 0 replies; 170+ messages in thread
From: Dmitry Gutov @ 2020-04-29 0:14 UTC (permalink / raw)
To: Paul Eggert
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 29.04.2020 03:04, Paul Eggert wrote:
> It's reasonable to have compile-time checking in a statically-typed language,
> though (as the above quote notes) the checking isn't adequate for C++ and one
> can get undefined behavior anyway in that language.
All the undefined-behavior stuff in the language is part of backward
compatibility with C. Like I said, the same argument that says "you can
change a const in C++" also says "string and int and void are basically
the same type".
> And we could add some
> similar compile-time checking for the Elisp byte-compiler: it could warn about
> misuses like (aset "abc" 0 ?d), for example.
Not the worst idea. Won't work: it's a dynamic language. Hence the
example of how a similar problem was dealt with in a fellow dynamic
language that I wrote about a couple of messages ago.
> However, any such compile-time checking would be either too restrictive (with
> false positives)
The "too restrictive" end of the spectrum will result in prohibiting the
user from modifying any and all conses.
> or only partial (with false negatives) or both (as in C++). So
> it wouldn't be an adequate substitute for documenting that some objects should
> not be changed.
With runtime checks, it could. But that might be too costly.
> I recall your using "literal object" but that's not a good choice of wording
> because the problem can occur with objects that are not literally present in any
> source code.
"Any object that is part of a literal value". You can probably extend
that sentence to be exhaustive.
> By "elsewhere" I meant in other language documentation (C/C++/etc.), not
> elsewhere in the emacs-27 manual.
In "etc", you mentioned Common Lisp previously. Any idea how it deals
with that problem?
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-28 17:47 ` Paul Eggert
@ 2020-04-29 0:32 ` Michael Heerdegen
2020-04-29 1:40 ` Paul Eggert
2020-04-29 16:36 ` Paul Eggert
0 siblings, 2 replies; 170+ messages in thread
From: Michael Heerdegen @ 2020-04-29 0:32 UTC (permalink / raw)
To: Paul Eggert
Cc: ke.vigouroux, 40671, Mattias Engdegård, Dmitry Gutov,
Richard Stallman
Paul Eggert <eggert@cs.ucla.edu> writes:
> On 4/28/20 10:25 AM, Drew Adams wrote:
> > Has anyone agreed with you
>
> Nobody's happy with the current documentation's language (not even
> me), but nobody has proposed specific wording improvements either.
I think the feedback would be better if you had been more cooperative/
open minded at the beginning. You have started committing stuff without
even asking whether people like your approach in general. What if
people think slight rewording is not enough? You started the thing not
very cooperatively, and that's how things developed. Just my point of
view.
> That's what committees do sometimes; we might not agree, but the guy
> who does most of the work generates something that nobody has the time
> to improve significantly.
We all do stuff here nobody else has time to do. Obviously, in this
case a collective brainstorming at the beginning would have been better.
Apart from questions like "please give me a better wording for this I
wrote if _you_ don't like it", why did you never ask "how could we
improve this aspect of the manual, what do you think?" or "do people
agree with what I have in mind?". Now stuff is already in the repo,
it's inconvenient to review, and the committer doesn't seem to be very
open to other perspectives.
A lot of the discussion here currently is rather destructive, yes,
that's not good, I guess everyone involved is to blame.
Michael.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-28 23:10 ` Paul Eggert
2020-04-28 23:36 ` Dmitry Gutov
2020-04-28 23:53 ` Dmitry Gutov
@ 2020-04-29 0:55 ` Drew Adams
2020-04-29 1:03 ` Dmitry Gutov
2020-04-29 1:38 ` Paul Eggert
2 siblings, 2 replies; 170+ messages in thread
From: Drew Adams @ 2020-04-29 0:55 UTC (permalink / raw)
To: Paul Eggert, Dmitry Gutov
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
> I don't see why we should depart from terminology used by
> C/C++/Fortran/Common Lisp/etc.; it's reasonably well-established.
You're _not_ using the language that's used for Common Lisp.
I echoed what the CL doc said. Elisp corresponds
to the behavior of CLTL1 in this regard, not to any
later update that makes the interpreter behave more
like compiled code (raising an error in both).
Like CLTL1, we should just warn about the gotcha,
not say that it's about modification or attempted
modification of "constants".
A few mails ago, you wondered if the disagreement
has been only about terminology. And the response
was mostly "Yes" - objections to your use of
"mutable" and "constant"/"immutable", and your use
of "cannot" instead of "should not" (aka "Don't").
You've since ignored that response, it seems. This
has dragged on, just circling. I, for one, give up.
But I do hope you'll listen to others. And yes,
Michael's point about committing before discussing
& deciding is spot on too. Remember your curly-quote
crusade? You did the same thing then, with similar
complaints about acting widely, unilaterally, and
prematurely.
My suggestion is to see how people have already
warned users about this gotcha here & there (forums
etc.) and do likewise. Come to an agreement about
the behavior to warn users about - in practical,
operational, but not exhaustive, terms.
A simple quoted-list example is enough, along with
a general description. Once there's agreement
about the message, including any example(s), the
wording will fall out naturally. (At least the
wording won't be a battleground, once the message
is decided on.)
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-29 0:55 ` Drew Adams
@ 2020-04-29 1:03 ` Dmitry Gutov
2020-04-29 1:15 ` Drew Adams
2020-04-29 1:38 ` Paul Eggert
1 sibling, 1 reply; 170+ messages in thread
From: Dmitry Gutov @ 2020-04-29 1:03 UTC (permalink / raw)
To: Drew Adams, Paul Eggert
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 29.04.2020 03:55, Drew Adams wrote:
> But I do hope you'll listen to others. And yes,
> Michael's point about committing before discussing
> & deciding is spot on too. Remember your curly-quote
> crusade? You did the same thing then, with similar
> complaints about acting widely, unilaterally, and
> prematurely.
I disagree about the comparison. The curly-quote was (still is) a
fiasco, a big scope of changes (and breakages) with comparatively little
practical benefit. This bug report at least deals with a real problem.
And of course it's much easier to criticize (what a lot of us have been
doing) than provide actual wording changes. So I wouldn't say committing
too soon was a significant problem in this particular instance. It's not
a far-reaching change, and we could still revert it.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-29 1:03 ` Dmitry Gutov
@ 2020-04-29 1:15 ` Drew Adams
2020-04-29 1:27 ` Michael Heerdegen
0 siblings, 1 reply; 170+ messages in thread
From: Drew Adams @ 2020-04-29 1:15 UTC (permalink / raw)
To: Dmitry Gutov, Paul Eggert
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
> > Remember your curly-quote
> > crusade? You did the same thing then, with similar
> > complaints about acting widely, unilaterally, and
> > prematurely.
>
> I disagree about the comparison. The curly-quote was (still is) a
> fiasco, a big scope of changes (and breakages) with comparatively
> little practical benefit. This bug report at least deals with a
> real problem.
Yes, I agree about that difference.
> And of course it's much easier to criticize (what a lot of us have been
> doing) than provide actual wording changes. So I wouldn't say
> committing too soon was a significant problem in this particular
> instance. It's not a far-reaching change, and we could still revert it.
And I agree with you there, too.
But I think Michael's point was about the
cooperation/attitude, not the nature or difficulty
of the problem to solve or the magnitude of any
problem of undoing committed changes.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-29 1:15 ` Drew Adams
@ 2020-04-29 1:27 ` Michael Heerdegen
0 siblings, 0 replies; 170+ messages in thread
From: Michael Heerdegen @ 2020-04-29 1:27 UTC (permalink / raw)
To: Drew Adams
Cc: ke.vigouroux, Paul Eggert, 40671, Mattias Engdegård,
Dmitry Gutov, Richard Stallman
Drew Adams <drew.adams@oracle.com> writes:
> But I think Michael's point was about the cooperation/attitude, not
> the nature or difficulty of the problem to solve or the magnitude of
> any problem of undoing committed changes.
Yes, I was referring to Paul's complaints and frustration, and I
wondered why the discussion developed like that. Maybe I'm totally
wrong, it's just how I experienced things.
Michael.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-29 0:55 ` Drew Adams
2020-04-29 1:03 ` Dmitry Gutov
@ 2020-04-29 1:38 ` Paul Eggert
2020-04-29 4:36 ` Drew Adams
2020-05-01 3:13 ` Dmitry Gutov
1 sibling, 2 replies; 170+ messages in thread
From: Paul Eggert @ 2020-04-29 1:38 UTC (permalink / raw)
To: Drew Adams, Dmitry Gutov
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 4/28/20 5:55 PM, Drew Adams wrote:
> You're _not_ using the language that's used for Common Lisp.
In what sense does the language differ? Here's a quote from CLtL2 (page 115):
"it is an error to destructively modify any object that appears as a constant
in executable code, whether within a 'quote' special form or as
a self-evaluating form."
This use of the word "constant" is consistent with what's in the emacs-27 doc.
> Elisp corresponds
> to the behavior of CLTL1 in this regard, not to any
> later update
Those older CLtL semantics were not well-defined, and to the extent that they
were defined were not followed by Common Lisp implementations. It's not clear
that the emacs-27 Elisp implementation corresponds to those older semantics, and
it's also not clear that documenting CLtL1 semantics would be a good idea for Elisp.
> A few mails ago, you wondered if the disagreement
> has been only about terminology. And the response
> was mostly "Yes" - objections to your use of
> "mutable" and "constant"/"immutable", and your use
> of "cannot" instead of "should not" (aka "Don't").
>
> You've since ignored that response, it seems.
I responded to those specific wording objections by removing the "immutable"s
and "cannots" that were objected to. At least, that was my intent; if I missed
something please let me know.
I admit I have not made changes in response to vaguer suggestions, but that's
partly because I don't really understand what's involved.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-29 0:32 ` Michael Heerdegen
@ 2020-04-29 1:40 ` Paul Eggert
2020-04-29 4:40 ` Michael Heerdegen
2020-04-29 16:36 ` Paul Eggert
1 sibling, 1 reply; 170+ messages in thread
From: Paul Eggert @ 2020-04-29 1:40 UTC (permalink / raw)
To: Michael Heerdegen
Cc: ke.vigouroux, 40671, Mattias Engdegård, Dmitry Gutov,
Richard Stallman
On 4/28/20 5:32 PM, Michael Heerdegen wrote:
> A lot of the discussion here currently is rather destructive, yes,
> that's not good, I guess everyone involved is to blame.
At this point the disagreement over a relatively minor terminology issue is so
lengthy that the whole documentation change is arguably more trouble than it's
worth. So again: anyone who wants to revert my recent doc changes to emacs-27 is
welcome to do so. Or, if you'd prefer to uniformly subsitute "literal object"
for "constant", please feel free to do that too. It's really not worth arguing
about, and I apologize for stirring up this hornet's nest.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-29 1:38 ` Paul Eggert
@ 2020-04-29 4:36 ` Drew Adams
2020-04-29 16:18 ` Paul Eggert
2020-05-01 3:13 ` Dmitry Gutov
1 sibling, 1 reply; 170+ messages in thread
From: Drew Adams @ 2020-04-29 4:36 UTC (permalink / raw)
To: Paul Eggert, Dmitry Gutov
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
> > You're _not_ using the language that's used
> > for Common Lisp.
>
> In what sense does the language differ? Here's
> a quote from CLtL2 (page 115):
>
> "it is an error to destructively modify any object that appears as a
> constant in executable code, whether within a 'quote' special form or as
> a self-evaluating form."
>
> This use of the word "constant" is consistent
> with what's in the emacs-27 doc.
I quoted that same text as part of a proposal to
FIX the very gotcha that Elisp still suffers from.
I already addressed this, specifically.
See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=40671#24
I specifically spoke of CLTL1, because its state,
and the state of CL at that time corresponds more
closely with that of Elisp and its doc, since CLTL1
predates the proposal to handle the gotcha
systematically.
> > Elisp corresponds to the behavior of CLTL1 in
> > this regard, not to any later update
>
> Those older CLtL semantics were not well-defined,
Precisely the problem Emacs Lisp has! And not
just not well defined. Different behavior
sometimes between interpreted and compiled code.
That IS the gotcha - the fact that Elisp does NOT
raise an error systematically in all such cases.
It does NOT always prevent you from modifying a
constant, quoted list etc.
Elisp is like CL was BEFORE the proposal I quoted,
which was adopted as the CLTL2 text you quoted.
They fixed the problem for CL by redefining CL
to not have it. For an implementation of CL to
follow the updated definition, it must provide
consistent behavior, preventing modification of
constants, quoted lists, etc.
Sound familiar yet?
> and to the extent that they were defined were not
> followed by Common Lisp implementations. It's not
> clear that the emacs-27 Elisp implementation
> corresponds to those older semantics, and it's
> also not clear that documenting CLtL1 semantics
> would be a good idea for Elisp.
The point is that the problem they fixed is the
problem Elisp still has. Whether it is exactly
the same in all particulars is unimportant -
it's about the behavior being undefined and not
necessarily the same if interpreted or compiled.
I mentioned the CL proposal, to take effect
for CLTL2, quoting:
"clarify that it is an error to destructively
^^^^^^^ ^^^^^^^^^^^^^^
modify objects which are self-evaluating
forms or which appear inside of a QUOTE
special form."
Why "clarify"? Because it was NOT stated as
part of the previous definition of CL that
that is an error. And that meant that CL
implementations were NOT required to
systematically raise an error to enforce that.
They did NOT always prevent you from modifying
such thingies.
The proposal also said:
"Disallowing modification of constants
^^^^^^^^^^^
consistently in all situations, rather than
^^^^^^^^^^^^
just in compiled code, is proposed because
^^^^^^^^^^^
in some compiled-only situations it may be
difficult to distinguish between "compiled"
and "interpreted" code."
That was the problem to be fixed, by raising an
error, i.e., by disallowing, in practice. And
that's exactly the problem that Elisp still has:
it does NOT disallow (systematic error). And no
amount of saying that it does (claiming you
"cannot" do it) changes that fact.
I quoted CLTL about the behavior before the
proposal, i.e., before systematically raising
an error:
"implicit sharing of compiled data structures
may result in unpredictable behavior if
^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^
destructive operations are performed. However,
CLtL does not explicitly allow or disallow
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
destructive operations on constants."
And about that I said:
Unpredictable behavior. It doesn't say it's
^^^^^^^
always impossible to modify such things. It
^^^^^^^^^^^^^^^^^
says, in effect, don't try.
^^^^^^^^^
That's what we should say for Emacs Lisp, since
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
we do NOT "disallow modification of constants
consistently in all situations."
For Emacs Lisp this is a gotcha, so we need a
SHOULD. If it were enforced as a MUST then we
wouldn't need such a caveat.
That's precisely the point. We do NOT disallow.
We do NOT always raise an error. We do NOT
always PREVENT changing quoted list structure etc.
AND SO we should NOT tell users that they CANNOT
do so - sometimes they CAN. We should instead
tell them that they SHOULD NOT try to do so, and
if they do then the resulting behavior is undefined.
___
I said last message that I gave up. And now I'm
literally repeating what I wrote 10 days ago.
You haven't heard, or you're not listening. (And
my impression is that others have said the same as
I, or similar.) Sorry, I'm done.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-29 1:40 ` Paul Eggert
@ 2020-04-29 4:40 ` Michael Heerdegen
2020-04-29 8:01 ` Eli Zaretskii
0 siblings, 1 reply; 170+ messages in thread
From: Michael Heerdegen @ 2020-04-29 4:40 UTC (permalink / raw)
To: Paul Eggert
Cc: ke.vigouroux, 40671, Mattias Engdegård, Dmitry Gutov,
Richard Stallman
Paul Eggert <eggert@cs.ucla.edu> writes:
> So again: anyone who wants to revert my recent doc changes to emacs-27
> is welcome to do so. Or, if you'd prefer to uniformly subsitute
> "literal object" for "constant"
I don't think "literal" covers all the cases you have in mind. I don't
have an idea for a name of the class of cases you have in mind, because
I would not subsume all examples you gave in one class at all. They
might be implementation- or memory-wise, but I don't think this is a good
perspective to describe a high-level language.
For example, the result of `symbol-name'. In my eyes, modifying the
result has a side effect (renaming the symbol, but in a way that is not
supported), and this side effect will have undesired consequences. But
that is true for other strings, too, that you would call mutable. It's
hard to draw a clear line here, unless you think (C-) implementation
wise.
For what you describe I would just say that under certain conditions
certain objects that are, in principle, mutable, should not be changed
in certain circumstances because of implementation details, here is a
list of such cases: ..., that's it.
I'm sorry that I also can't offer patches because I don't speak texinfo.
> It's really not worth arguing about, and I apologize for stirring up
> this hornet's nest.
I've never been called a hornet before.
Michael.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-29 4:40 ` Michael Heerdegen
@ 2020-04-29 8:01 ` Eli Zaretskii
0 siblings, 0 replies; 170+ messages in thread
From: Eli Zaretskii @ 2020-04-29 8:01 UTC (permalink / raw)
To: Michael Heerdegen; +Cc: ke.vigouroux, eggert, 40671, mattiase, dgutov, rms
> From: Michael Heerdegen <michael_heerdegen@web.de>
> Date: Wed, 29 Apr 2020 06:40:39 +0200
> Cc: ke.vigouroux@laposte.net, 40671@debbugs.gnu.org,
> Mattias Engdegård <mattiase@acm.org>,
> Dmitry Gutov <dgutov@yandex.ru>, Richard Stallman <rms@gnu.org>
>
> I'm sorry that I also can't offer patches because I don't speak texinfo.
Would you be willing to review the relevant portions of the manual and
post comments to the parts that in your opinion need further work? I
think that would be a good step towards making the text less
controversial.
TIA
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-29 4:36 ` Drew Adams
@ 2020-04-29 16:18 ` Paul Eggert
2020-05-01 2:47 ` Richard Stallman
0 siblings, 1 reply; 170+ messages in thread
From: Paul Eggert @ 2020-04-29 16:18 UTC (permalink / raw)
To: Drew Adams, Dmitry Gutov
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 4/28/20 9:36 PM, Drew Adams wrote:
> Elisp is like CL was BEFORE the proposal I quoted,
No, that's backwards. CLtL1 was hazy, but arguably would have disallowed Elisp's
behavior because it arguably required the interpreter to immediately respond to
changes in objects currently being executed, and arguably required the
interpreter to not coalesce identical literals, and the Elisp interpreter
violates both requirements. In contrast, CLtL2 allows the Elisp behavior, so
CLtL2 is the better way to go here.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-29 0:32 ` Michael Heerdegen
2020-04-29 1:40 ` Paul Eggert
@ 2020-04-29 16:36 ` Paul Eggert
1 sibling, 0 replies; 170+ messages in thread
From: Paul Eggert @ 2020-04-29 16:36 UTC (permalink / raw)
To: Michael Heerdegen
Cc: ke.vigouroux, 40671, Mattias Engdegård, Dmitry Gutov,
Richard Stallman
[-- Attachment #1: Type: text/plain, Size: 496 bytes --]
On 4/28/20 5:32 PM, Michael Heerdegen wrote:
> Now stuff is already in the repo, it's inconvenient to review,
I took the trouble of retrieving all changes to the emacs-27 documentation since
this exercise started, discarding the irrelevant changes, with the result being
the attached diff. This should make the new material more convenient to review.
Of course this is not a complete substitute for reviewing what's in the manual
now, as I could have well missed some stuff that needs changing.
[-- Attachment #2: constants.diff --]
[-- Type: text/x-patch, Size: 20883 bytes --]
diff --git a/doc/lispintro/emacs-lisp-intro.texi b/doc/lispintro/emacs-lisp-intro.texi
index 66aa97e20a..ea16d9ef15 100644
--- a/doc/lispintro/emacs-lisp-intro.texi
+++ b/doc/lispintro/emacs-lisp-intro.texi
@@ -7317,11 +7317,21 @@ setcar
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 @@ setcdr
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 @@ kill-new function
@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 @@ cons & search-fwd Review
@smallexample
@group
-(setq triple '(1 2 3))
+(setq triple (list 1 2 3))
(setcar triple '37)
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 @@ Printing in Edebug
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/elisp.texi b/doc/lispref/elisp.texi
index cfd96f7aa6..bba1b63115 100644
--- a/doc/lispref/elisp.texi
+++ b/doc/lispref/elisp.texi
@@ -297,6 +297,7 @@ Top
* 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.
Programming Types
diff --git a/doc/lispref/eval.texi b/doc/lispref/eval.texi
index cd45c8df03..baddce4d9c 100644
--- a/doc/lispref/eval.texi
+++ b/doc/lispref/eval.texi
@@ -158,6 +158,12 @@ Self-Evaluating Forms
@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
+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}.
+
It is common to write numbers, characters, strings, and even vectors
in Lisp code, taking advantage of the fact that they self-evaluate.
However, it is quite unusual to do this for types that lack a read
@@ -558,6 +564,8 @@ Quoting
@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}.
@end defspec
@cindex @samp{'} for quoting
@@ -598,6 +606,12 @@ Quoting
@end group
@end example
+ 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}.
+
Other quoting constructs include @code{function} (@pxref{Anonymous
Functions}), which causes an anonymous lambda expression written in Lisp
to be compiled, and @samp{`} (@pxref{Backquote}), which is used to quote
@@ -695,6 +709,9 @@ Backquote
@end group
@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.
@node Eval
@section Eval
diff --git a/doc/lispref/keymaps.texi b/doc/lispref/keymaps.texi
index fd269d520c..1e81fb1dc5 100644
--- a/doc/lispref/keymaps.texi
+++ b/doc/lispref/keymaps.texi
@@ -1441,10 +1441,10 @@ Changing Key Bindings
@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..ea44e01f48 100644
--- a/doc/lispref/lists.texi
+++ b/doc/lispref/lists.texi
@@ -866,10 +866,15 @@ List Variables
@node Modifying Lists
@section Modifying Existing List Structure
@cindex destructive list operations
+@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 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}.
@cindex CL note---@code{rplaca} vs @code{setcar}
@quotation
@@ -906,7 +911,7 @@ Setcar
@example
@group
-(setq x '(1 2))
+(setq x (list 1 2)) ; @r{Create a mutable list.}
@result{} (1 2)
@end group
@group
@@ -926,8 +931,8 @@ Setcar
@example
@group
-;; @r{Create two lists that are partly shared.}
-(setq x1 '(a b c))
+;; @r{Create two mutable lists that are partly shared.}
+(setq x1 (list 'a 'b 'c))
@result{} (a b c)
(setq x2 (cons 'z (cdr x1)))
@result{} (z b c)
@@ -1017,11 +1022,11 @@ Setcdr
@example
@group
-(setq x '(1 2 3))
+(setq x (list 1 2 3)) ; @r{Create a mutable list.}
@result{} (1 2 3)
@end group
@group
-(setcdr x '(4))
+(setcdr x '(4)) ; @r{Modify the list's tail to be a constant list.}
@result{} (4)
@end group
@group
@@ -1037,7 +1042,7 @@ Setcdr
@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 +1074,7 @@ Setcdr
@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,11 +1135,11 @@ Rearrangement
@example
@group
-(setq x '(1 2 3))
+(setq x (list 1 2 3)) ; @r{Create a mutable list.}
@result{} (1 2 3)
@end group
@group
-(nconc x '(4 5))
+(nconc x '(4 5)) ; @r{Modify the list's tail to be a constant list.}
@result{} (1 2 3 4 5)
@end group
@group
@@ -1150,7 +1155,7 @@ Rearrangement
@example
@group
-(setq x '(1 2 3))
+(setq x (list 1 2 3))
@result{} (1 2 3)
@end group
@group
@@ -1163,11 +1168,13 @@ Rearrangement
@end group
@end example
-However, the other arguments (all but the last) must be lists.
+However, the other arguments (all but the last) should 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:
+A common pitfall is to use a constant list as a non-last
+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
@@ -1270,7 +1277,7 @@ Sets And Lists
@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 +1310,12 @@ Sets And Lists
(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 +1331,7 @@ Sets And Lists
@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
@@ -1349,12 +1356,12 @@ Sets And Lists
@example
@group
-(memql 1.2 '(1.1 1.2 1.3)) ; @r{@code{1.2} and @code{1.2} are @code{eql}.}
+(memql 1.2 '(1.1 1.2 1.3)) ; @r{@code{1.2} and @code{1.2} must be @code{eql}.}
@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}.}
- @result{} nil
+(memq 1.2 '(1.1 1.2 1.3)) ; @r{@code{1.2} and @code{1.2} need not be @code{eq}.}
+ @result{} nil ; @r{... or it might be @code{(1.2 1.3)}.}
@end group
@end example
@end defun
@@ -1373,11 +1380,11 @@ Sets And Lists
@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 +1414,7 @@ Sets And Lists
@example
@group
-(setq l '((2) (1) (2)))
+(setq l (list '(2) '(1) '(2)))
(delete '(2) l)
@result{} ((1))
l
@@ -1416,7 +1423,7 @@ Sets And Lists
;; @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
@@ -1619,7 +1626,7 @@ Association Lists
("compound leaves" . horsechestnut)))
(assq "simple leaves" leaves)
- @result{} nil
+ @result{} @r{Unspecified; might be @code{nil} or non-@code{nil}.}
(assoc "simple leaves" leaves)
@result{} ("simple leaves" . oak)
@end smallexample
@@ -1759,7 +1766,7 @@ Association Lists
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 +1933,7 @@ Plist Access
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/objects.texi b/doc/lispref/objects.texi
index 1c4e7e4d4e..1d5b2c690f 100644
--- a/doc/lispref/objects.texi
+++ b/doc/lispref/objects.texi
@@ -46,6 +46,10 @@ Lisp Data Types
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.
@@ -59,6 +63,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.
@end menu
@node Printed Representation
@@ -2373,3 +2378,52 @@ Equality Predicates
@end group
@end example
@end defun
+
+@node Constants and Mutability
+@section Constants and Mutability
+@cindex constants
+@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.
+
+ 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.
+
+ 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}.
+
+ 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.
+
+ 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.
+
+ When the same constant occurs multiple times in a program, the Lisp
+interpreter might save time or space by reusing existing constants or
+constant 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
+instances. Lisp programs should be written so that they work
+regardless of whether this optimization is in use.
diff --git a/doc/lispref/sequences.texi b/doc/lispref/sequences.texi
index d89aa31e4c..1cb0d05cc7 100644
--- a/doc/lispref/sequences.texi
+++ b/doc/lispref/sequences.texi
@@ -183,11 +183,11 @@ Sequence Functions
@example
@group
-(setq bar '(1 2))
+(setq bar (list 1 2)) ; @r{Create a mutable list.}
@result{} (1 2)
@end group
@group
-(setq x (vector 'foo bar))
+(setq x (vector 'foo bar)) ; @r{Create a mutable vector.}
@result{} [foo (1 2)]
@end group
@group
@@ -278,7 +278,7 @@ Sequence Functions
@example
@group
-(setq x '(a b c))
+(setq x (list 'a 'b 'c)) ; @r{Create a mutable list.}
@result{} (a b c)
@end group
@group
@@ -320,7 +320,7 @@ Sequence Functions
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])) ; @r{Create a mutable vector.}
@result{} [1 2 3 4]
(nreverse x)
@result{} [4 3 2 1]
@@ -330,7 +330,7 @@ Sequence Functions
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,7 +374,7 @@ Sequence Functions
@example
@group
-(setq nums '(1 3 2 6 5 4 0))
+(setq nums (list 1 3 2 6 5 4 0)) ; @r{Create a mutable list.}
@result{} (1 3 2 6 5 4 0)
@end group
@group
@@ -1228,7 +1228,7 @@ Array Functions
@example
@group
-(setq w [foo bar baz])
+(setq w (vector 'foo 'bar 'baz)) ; @r{Create a mutable vector.}
@result{} [foo bar baz]
(aset w 0 'fu)
@result{} fu
@@ -1237,7 +1237,8 @@ Array Functions
@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 @@ Array Functions
@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}.
+
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,8 @@ Array Functions
@example
@group
-(setq a [a b c d e f g])
+;; @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)
@result{} [0 0 0 0 0 0 0]
@@ -1265,7 +1271,8 @@ Array Functions
@result{} [0 0 0 0 0 0 0]
@end group
@group
-(setq s "When in the course")
+;; @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 ?-)
@result{} "------------------"
@@ -1302,7 +1309,9 @@ Vectors
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.
-@xref{Self-Evaluating Forms}.
+@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}.
Here are examples illustrating these principles:
diff --git a/doc/lispref/strings.texi b/doc/lispref/strings.texi
index 14cabc5d79..a4c9c2549c 100644
--- a/doc/lispref/strings.texi
+++ b/doc/lispref/strings.texi
@@ -51,10 +51,8 @@ String Basics
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 @@ String Basics
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,11 @@ Modifying Strings
@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.
+@xref{Constants and Mutability}.
+
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 +597,7 @@ Text Comparison
@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 +614,7 @@ Text Comparison
@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
^ permalink raw reply related [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-29 16:18 ` Paul Eggert
@ 2020-05-01 2:47 ` Richard Stallman
2020-05-01 6:23 ` Eli Zaretskii
0 siblings, 1 reply; 170+ messages in thread
From: Richard Stallman @ 2020-05-01 2:47 UTC (permalink / raw)
To: Paul Eggert; +Cc: ke.vigouroux, 40671, michael_heerdegen, mattiase, dgutov
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
To a purist, the vagueness about what happens to Emacs if you modify
code at the wrong time may seem intolerable. If there were an easy
and painless way to implement well-defined behavior, it might be worth
doing so. But there isn't.
This isn't a big difficulty in practice. It isn't worth sacrificing
anything that matters.
--
Dr Richard Stallman
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-18 21:54 ` Drew Adams
2020-04-19 2:39 ` Noam Postavsky
2020-04-19 20:39 ` Paul Eggert
@ 2020-05-01 3:03 ` Dmitry Gutov
2020-05-01 5:16 ` Drew Adams
2020-05-01 21:46 ` Paul Eggert
2 siblings, 2 replies; 170+ messages in thread
From: Dmitry Gutov @ 2020-05-01 3:03 UTC (permalink / raw)
To: Drew Adams, Paul Eggert, Mattias Engdegård
Cc: Kevin Vigouroux, 40671-done
On 19.04.2020 00:54, Drew Adams wrote:
> It's about code that always creates new list
> structure, versus code that might create new
> list structure only sometimes (e.g. the first
> time it's encountered).
Could we call them "interned values"? Like "interned strings" in some
programming languages. And then say "don't try to modify them please".
The "sometimes" aspect is a semantic snag, but it's certainly better
than calling them constant.
"literal values" is also an option, but that definition seems limiting.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-04-29 1:38 ` Paul Eggert
2020-04-29 4:36 ` Drew Adams
@ 2020-05-01 3:13 ` Dmitry Gutov
2020-05-01 5:15 ` Drew Adams
2020-05-01 21:40 ` Paul Eggert
1 sibling, 2 replies; 170+ messages in thread
From: Dmitry Gutov @ 2020-05-01 3:13 UTC (permalink / raw)
To: Paul Eggert, Drew Adams
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 29.04.2020 04:38, Paul Eggert wrote:
> On 4/28/20 5:55 PM, Drew Adams wrote:
>> You're_not_ using the language that's used for Common Lisp.
> In what sense does the language differ? Here's a quote from CLtL2 (page 115):
>
> "it is an error to destructively modify any object that appears as a constant
> in executable code, whether within a 'quote' special form or as
> a self-evaluating form."
As Drew pointed out (and if I understood this correctly), the above
specification leads to implementations that do raise an error when
someone tried to modify such a value.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-01 3:13 ` Dmitry Gutov
@ 2020-05-01 5:15 ` Drew Adams
2020-05-01 21:40 ` Paul Eggert
1 sibling, 0 replies; 170+ messages in thread
From: Drew Adams @ 2020-05-01 5:15 UTC (permalink / raw)
To: Dmitry Gutov, Paul Eggert
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
> >> You're _not_ using the language that's used for Common Lisp.
> > In what sense does the language differ? Here's a quote from CLtL2
> (page 115):
> >
> > "it is an error to destructively modify any object that appears as a
> constant
> > in executable code, whether within a 'quote' special form or as
> > a self-evaluating form."
>
> As Drew pointed out (and if I understood this correctly), the above
> specification leads to implementations that do raise an error when
> someone tried to modify such a value.
That's my understanding. I believe that wasn't
the case for CLTL(1) - there was no such promise
or requirement. And I think it's also not the
case for Elisp. Like CLTL(1), we should just
warn users about the gotcha, since there's no
protection from it.
To be clear, I'm no expert on CLTL2. I used
CL for years before that. The gotcha bit me
once, having modified the result of a quoted
list - and then someone explained what was
happening.
It's too easy for a newbie to think only in
terms of textual source code being interpreted.
It's easy not to realize, as Michael said, that
there's the Lisp reader, the interpreter, and
the byte-compiler, and each might get a chance
to handle a quoted list. And just how they did
so was not specified.
Presumably, a conformant CL implementation now
protects you from this gotcha.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-01 3:03 ` Dmitry Gutov
@ 2020-05-01 5:16 ` Drew Adams
2020-05-01 21:46 ` Paul Eggert
1 sibling, 0 replies; 170+ messages in thread
From: Drew Adams @ 2020-05-01 5:16 UTC (permalink / raw)
To: Dmitry Gutov, Paul Eggert, Mattias Engdegård
Cc: Kevin Vigouroux, 40671-done
> > It's about code that always creates new list
> > structure, versus code that might create new
> > list structure only sometimes (e.g. the first
> > time it's encountered).
>
> Could we call them "interned values"? Like "interned strings" in some
> programming languages. And then say "don't try to modify them please".
>
> The "sometimes" aspect is a semantic snag, but it's certainly better
> than calling them constant.
>
> "literal values" is also an option, but that definition seems limiting.
You're replying to a message of mine from a
while back. I agree with the limitation or
difficulty of communicating the "sometimes"
aspect. And I agree that the message for users
should be "don't try to modify them" (even
though the "them" isn't detailed).
My own opinion is to avoid mention of any such
name: constant, literal, interned this-or-that.
Better to keep it vague, and just sketch the
problem and say that the behavior is undefined.
IMO, the message for users for the quoted-list
gotcha should be to not assume that code that
has a quoted list in it creates a new list
whenever you might think that that code (Lisp
source or byte-compiled) gets evaluated.
`quote' returns its arg unevaluated, but it's
not always clear by looking at the source code
just when or how many times a quoted list might
get evaluated. That's undefined, so assume
nothing about it. In particular, the behavior
can differ for the same source code, depending
on whether it's interpreted or byte-compiled.
A simple example could suffice, to make that
point.
If it helps, we can also say, for the example,
that the source-code quoted list might, in
effect, get replaced by its value when it's
read or byte-compiled, so the same cons cells
(not new list structure) might get reused each
time the resulting code gets evaluated.
And because of that possibility you're advised
not to try to modify such a list.
Yes, there are other examples of the problem,
besides quoted lists. Like the Common Lisp
doc, we could list some of them, without
giving more examples or going into detail.
Or we could give a second simple example,
perhaps with a string literal.
What's important, I think, is to (1) get
across the general idea/problem, (2) give
some idea how to recognize situations where
the gotcha can arise, and make clear that
you cannot depend on the behavior.
There's no prevention of the gotcha, e.g. by
raising an error systematically. You just
have to learn to recognize the possibility of
trying to modify something that may have
become, at some point, effectively
unmodifiable - and not do that.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-01 2:47 ` Richard Stallman
@ 2020-05-01 6:23 ` Eli Zaretskii
0 siblings, 0 replies; 170+ messages in thread
From: Eli Zaretskii @ 2020-05-01 6:23 UTC (permalink / raw)
To: rms; +Cc: ke.vigouroux, eggert, 40671, michael_heerdegen, mattiase, dgutov
> From: Richard Stallman <rms@gnu.org>
> Date: Thu, 30 Apr 2020 22:47:32 -0400
> Cc: ke.vigouroux@laposte.net, 40671@debbugs.gnu.org, michael_heerdegen@web.de,
> mattiase@acm.org, dgutov@yandex.ru
>
> To a purist, the vagueness about what happens to Emacs if you modify
> code at the wrong time may seem intolerable. If there were an easy
> and painless way to implement well-defined behavior, it might be worth
> doing so. But there isn't.
>
> This isn't a big difficulty in practice. It isn't worth sacrificing
> anything that matters.
I agree, but the practical problem is that we have a couple of purists
on board, for whom this is an itch they scratch not too infrequently.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-01 3:13 ` Dmitry Gutov
2020-05-01 5:15 ` Drew Adams
@ 2020-05-01 21:40 ` Paul Eggert
2020-05-01 22:05 ` Drew Adams
2020-05-02 1:07 ` Dmitry Gutov
1 sibling, 2 replies; 170+ messages in thread
From: Paul Eggert @ 2020-05-01 21:40 UTC (permalink / raw)
To: Dmitry Gutov, Drew Adams
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 4/30/20 8:13 PM, Dmitry Gutov wrote:
> On 29.04.2020 04:38, Paul Eggert wrote:
>> Here's a quote from CLtL2 (page 115):
>>
>> "it is an error to destructively modify any object that appears as a constant
>> in executable code, whether within a 'quote' special form or as
>> a self-evaluating form."
>
> As Drew pointed out (and if I understood this correctly), the above
> specification leads to implementations that do raise an error when someone tried
> to modify such a value.
Although those implementations conform to the Common Lisp spec, that's because
the spec explicitly says such behavior is undefined - which means
implementations can signal an error, dump core, or do whatever else they want.
See <https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node11.html>, which uses
"should" in the same sense the emacs-27 elisp manual uses "should". Here's a quote:
-----
When this book specifies that it "is an error" for some situation to occur, this
means that:
* No valid Common Lisp program should cause this situation to occur.
* If this situation occurs, the effects and results are completely undefined as
far as adherence to the Common Lisp specification is concerned.
* No Common Lisp implementation is required to detect such an error. Of course,
implementors are encouraged to provide for detection of such errors wherever
reasonable.
This is not to say that some particular implementation might not define the
effects and results for such a situation; the point is that no program
conforming to the Common Lisp specification may correctly depend on such effects
or results.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-01 3:03 ` Dmitry Gutov
2020-05-01 5:16 ` Drew Adams
@ 2020-05-01 21:46 ` Paul Eggert
2020-05-01 23:37 ` Dmitry Gutov
1 sibling, 1 reply; 170+ messages in thread
From: Paul Eggert @ 2020-05-01 21:46 UTC (permalink / raw)
To: Dmitry Gutov, Drew Adams, Mattias Engdegård
Cc: Kevin Vigouroux, 40671-done
On 4/30/20 8:03 PM, Dmitry Gutov wrote:
> Could we call them "interned values"? Like "interned strings" in some
> programming languages.
"Interned" would imply that we're merely deduplicating objects by hashing their
contents, which means modifying one deduplicated object modifies them all. But
the problem is bigger than that. There are some objects that one simply should
not modify, even if they are not deduplicated.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-01 21:40 ` Paul Eggert
@ 2020-05-01 22:05 ` Drew Adams
2020-05-01 22:28 ` Paul Eggert
2020-05-02 1:07 ` Dmitry Gutov
1 sibling, 1 reply; 170+ messages in thread
From: Drew Adams @ 2020-05-01 22:05 UTC (permalink / raw)
To: Paul Eggert, Dmitry Gutov
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
> >> Here's a quote from CLtL2 (page 115):
> >>
> >> "it is an error to destructively modify any object that appears as a
> >> constant in executable code, whether within a 'quote' special form or as
> >> a self-evaluating form."
> >
> > As Drew pointed out (and if I understood this correctly), the above
> > specification leads to implementations that do raise an error when
> > someone tried to modify such a value.
>
> Although those implementations conform to the Common Lisp spec, that's
> because the spec explicitly says such behavior is undefined - which means
> implementations can signal an error, dump core, or do whatever else
> they want.
> See
> <https://urldefense.com/v3/__https://www.cs.cmu.edu/Groups/AI/html/cltl
> /clm/node11.html__;!!GqivPVa7Brio!NeqWMrCFKgi8Ktwdz5aIkeBh_-TPzH-
> XiJbWDMeSRu1VKiI70b5LK6Sy2v5CMxaq$ >, which uses
> "should" in the same sense the emacs-27 elisp manual uses "should".
I stand corrected. I was assuming that the "proposal"
I cited had actually been adopted for CLTL2.
So CLTL2 is in the same boat as CLTL(1), in the regard
relevant to this thread: There is NO systematic raising
of an error - no prevention of the gotcha.
So what I said about Elisp being like CLTL(1) applies
also to CLTL2: We should NOT say that you _cannot_
do XYZ (because you might be able to, and the behavior
if you try is undefined). We should instead say that
you _should not_.
We're still circling, though. But thanks for clarifying
that "it's an error" meaning. I misremembered that as
meaning that a conformant implementation is required to
raise an error. I was thinking/assuming that the cited
proposal was in fact adopted as part of the CL definition.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-01 22:05 ` Drew Adams
@ 2020-05-01 22:28 ` Paul Eggert
0 siblings, 0 replies; 170+ messages in thread
From: Paul Eggert @ 2020-05-01 22:28 UTC (permalink / raw)
To: Drew Adams, Dmitry Gutov
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 5/1/20 3:05 PM, Drew Adams wrote:
> We should NOT say that you _cannot_
> do XYZ (because you might be able to, and the behavior
> if you try is undefined). We should instead say that
> you _should not_.
That's what the emacs-27 manual does now.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-01 21:46 ` Paul Eggert
@ 2020-05-01 23:37 ` Dmitry Gutov
0 siblings, 0 replies; 170+ messages in thread
From: Dmitry Gutov @ 2020-05-01 23:37 UTC (permalink / raw)
To: Paul Eggert, Drew Adams, Mattias Engdegård
Cc: Kevin Vigouroux, 40671-done
On 02.05.2020 00:46, Paul Eggert wrote:
> On 4/30/20 8:03 PM, Dmitry Gutov wrote:
>> Could we call them "interned values"? Like "interned strings" in some
>> programming languages.
> "Interned" would imply that we're merely deduplicating objects by hashing their
> contents, which means modifying one deduplicated object modifies them all. But
> the problem is bigger than that. There are some objects that one simply should
> not modify, even if they are not deduplicated.
True. It's just the closest term from other languages I know that I
could think of.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-01 21:40 ` Paul Eggert
2020-05-01 22:05 ` Drew Adams
@ 2020-05-02 1:07 ` Dmitry Gutov
2020-05-02 6:28 ` Paul Eggert
1 sibling, 1 reply; 170+ messages in thread
From: Dmitry Gutov @ 2020-05-02 1:07 UTC (permalink / raw)
To: Paul Eggert, Drew Adams
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 02.05.2020 00:40, Paul Eggert wrote:
>> As Drew pointed out (and if I understood this correctly), the above
>> specification leads to implementations that do raise an error when someone tried
>> to modify such a value.
>
> Although those implementations conform to the Common Lisp spec, that's because
> the spec explicitly says such behavior is undefined - which means
> implementations can signal an error, dump core, or do whatever else they want.
> See <https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node11.html>, which uses
> "should" in the same sense the emacs-27 elisp manual uses "should".
I suppose so.
> When this book specifies that it "is an error" for some situation to occur, this
> means that:
>
> * No valid Common Lisp program should cause this situation to occur.
>
> * If this situation occurs, the effects and results are completely undefined as
> far as adherence to the Common Lisp specification is concerned.
>
> * No Common Lisp implementation is required to detect such an error. Of course,
> implementors are encouraged to provide for detection of such errors wherever
> reasonable.
>
> This is not to say that some particular implementation might not define the
> effects and results for such a situation; the point is that no program
> conforming to the Common Lisp specification may correctly depend on such effects
> or results.
Indeed.
I took a longer look around the CLtL, to see how the term "constant" is
used there, though. Some phrases:
---
...it is an error to destructively modify any object that appears as
a constant in executable code, whether as a self-evaluating form or
within a quote special form
...to specify what objects can be in compiled constants...
quoted constants in it are similar in this sense to quoted constants
in the corresponding source code
An object may be used as a quoted constant...
Some types of objects, such as streams, are not supported in
constants processed by the file compiler. Such objects may not portably
appear as constants in code processed with compile-file.
The following terms are used throughout this section. The term
constant refers to a quoted or self-evaluating constant, not a named
constant defined by defconstant.
Two objects are similar as a constant if and only if they are both of
one of the types listed below and satisfy...
Two conses are similar as constants if the values of their respective
car and cdr attributes are similar as constants.
(Then comes the description of "similar as constants" values being
coalesced in compiled code).
---
CL's terminology seems fairly old by today's standards, but it looks
like they were grasping for words, just as we are now.
They very rarely use the phrase "constant objects", however. Instead,
it's almost always "objects that appears as a constant [in code]",
"object ... used as a quoted constant", "object may not ... appear as
constants in code", "objects are similar as a constant".
IOW, it's the difference between constant values and constant pointers
to [mutable] values. And the users are advised not to change the objects
that "appear as constants"/[play the role of constants]/[are the values
of constants] in executable code.
And there is no juxtaposition of "mutable objects" vs "constant objects"
anywhere in there, with "constant" defined like that, which is the part
of our new documentation that really got me into this discussion. So the
section "Constants and Mutability", even though it has valuable
information, could use a full rewrite. And could probably move to end of
the "Self-Evaluating Forms" section.
I'm also not sure it's a good idea to add too much explanations to the
introduction featuring phrases like "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", so I'd keep the changes in the examples (the ones I
looked at look sensible), but remove most of the explanations. Moreso
that they are using the phrases "mutable values" and "constant values".
Some short explanation could say that it's a bad idea to modify a quoted
form (and then reference "Self-Evaluating Forms").
I can try to make a patch, but at this point is would consist mostly of
deletions.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-02 1:07 ` Dmitry Gutov
@ 2020-05-02 6:28 ` Paul Eggert
2020-05-02 15:42 ` Dmitry Gutov
0 siblings, 1 reply; 170+ messages in thread
From: Paul Eggert @ 2020-05-02 6:28 UTC (permalink / raw)
To: Dmitry Gutov, Drew Adams
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 5/1/20 6:07 PM, Dmitry Gutov wrote:
> They very rarely use the phrase "constant objects", however. Instead, it's
> almost always "objects that appears as a constant [in code]", "object ... used
> as a quoted constant", "object may not ... appear as constants in code",
> "objects are similar as a constant".
We could use similar circumlocutions. Or instead of saying "constant" we could
say "unchanging", as distinct from "unchangeable". (It beats
"object-that-should-not-be-changed" or "glass object - you changed it, you broke
it!". :-) The usual word for this notion is "constant", though.
> IOW, it's the difference between constant values and constant pointers to
> [mutable] values.
I don't see that. A constant (or "unchanging") string is like a mutable string,
except you shouldn't change it. There's no sense in CLtL in which a mutable
object must be implemented via a pointer to a value whereas a constant must not
be implemented that way.
> there is no juxtaposition of "mutable objects" vs "constant objects"
> anywhere in there
Yes, the mutable/immutable terminology revolution happened mostly after CLtL was
written.
> So the section
> "Constants and Mutability", even though it has valuable information, could use a
> full rewrite. And could probably move to end of the "Self-Evaluating Forms"
> section.
Whether an object is constant is distinct from whether it's derived from a
self-evaluating form, because one can have constants that were never derived
from any self-evaluating form. Any doc rewrite should be careful to keep the two
notions distinct, quite plausibily (though not necessarily) in different sections.
> I can try to make a patch, but at this point is would consist mostly of deletions.
Certainly some stuff could be deleted (the tutorial could be trimmed as you
suggest, for example), but we should keep the baby while we're throwing out the
bathwater. And if we're using circumlocutions the text is likely to get longer,
not shorter.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-02 6:28 ` Paul Eggert
@ 2020-05-02 15:42 ` Dmitry Gutov
2020-05-02 19:35 ` Paul Eggert
0 siblings, 1 reply; 170+ messages in thread
From: Dmitry Gutov @ 2020-05-02 15:42 UTC (permalink / raw)
To: Paul Eggert, Drew Adams
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 02.05.2020 09:28, Paul Eggert wrote:
> On 5/1/20 6:07 PM, Dmitry Gutov wrote:
>
>> They very rarely use the phrase "constant objects", however. Instead, it's
>> almost always "objects that appears as a constant [in code]", "object ... used
>> as a quoted constant", "object may not ... appear as constants in code",
>> "objects are similar as a constant".
>
> We could use similar circumlocutions. Or instead of saying "constant" we could
> say "unchanging", as distinct from "unchangeable". (It beats
> "object-that-should-not-be-changed" or "glass object - you changed it, you broke
> it!". :-) The usual word for this notion is "constant", though.
"glass objects" or "voldemort objects" all sound better to me. :-)
"unchanging" is one of the meanings of "constant". It's a property of a
process, not something we can call a value out of context.
CLtL uses the term "coalesced", though. We can consider it.
>> IOW, it's the difference between constant values and constant pointers to
>> [mutable] values.
>
> I don't see that. A constant (or "unchanging") string is like a mutable string,
> except you shouldn't change it.
An unchanging string is just a string that nobody changed. "Please don't
change unchanging strings" is a prohibition of time travel.
> There's no sense in CLtL in which a mutable
> object must be implemented via a pointer to a value whereas a
constant must not
> be implemented that way.
The "objects that appear as a constant" are objects to which exist
references from executable code, and where such references are
"constant" (or possibly constant, since an implementation might opt not
to coalesce the values). That why it's about constant references (and
objects to which such references exist).
>> there is no juxtaposition of "mutable objects" vs "constant objects"
>> anywhere in there
>
> Yes, the mutable/immutable terminology revolution happened mostly after CLtL was
> written.
Not just because of that.
>> So the section
>> "Constants and Mutability", even though it has valuable information, could use a
>> full rewrite. And could probably move to end of the "Self-Evaluating Forms"
>> section.
>
> Whether an object is constant is distinct from whether it's derived from a
> self-evaluating form, because one can have constants that were never derived
> from any self-evaluating form.
Examples?
I mean,
A mutable object can become constant if it is part of an expression
that is evaluated
does add some cases not covered by self-evaluating forms, but those are
more complex cases (e.g. creating forms programmatically and then
passing them to 'eval'), and then the programmer might justifiably be
expected to use their head. The self-evaluating forms case is arguably
less obvious.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-02 15:42 ` Dmitry Gutov
@ 2020-05-02 19:35 ` Paul Eggert
2020-05-03 1:30 ` Dmitry Gutov
0 siblings, 1 reply; 170+ messages in thread
From: Paul Eggert @ 2020-05-02 19:35 UTC (permalink / raw)
To: Dmitry Gutov, Drew Adams
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
>> There's no sense in CLtL in which a mutable
>> object must be implemented via a pointer to a value whereas a constant must not
>> be implemented that way.
>
> The "objects that appear as a constant" are objects to which exist references
> from executable code, and where such references are "constant" (or possibly
> constant, since an implementation might opt not to coalesce the values). That
> why it's about constant references (and objects to which such references exist).
I don't understand this point.
It sounds like you might be trying to distinguish between constant references
(i.e., pointers that don't change) and constant objects implemented via
references (i.e., the pointed-to values don't change). However, whether the
references themselves are constant is independent of the issue at hand. The
issue wouldn't change, for example, if Emacs relocated objects so that
references were updated regardless of whether the objects' values were constant.
>> Whether an object is constant is distinct from whether it's derived from a
>> self-evaluating form, because one can have constants that were never derived
>> from any self-evaluating form.
>
> Examples?
One example is (aset (symbol-name 'car) 0 ?d), which I mentioned a while ago.
Here's a trickier one:
(let ((constant-string (aref (symbol-function 'error) 1)))
(aset constant-string 0 183)
(number-sequence 0 1 0))
This also provokes undefined behavior at the C level while number-sequence is
doing its thing; my Emacs dumps core, yours may do something different. I'm sure
there are other examples. The point is that programs should not modify constants.
It would be nice if Emacs reliably signaled these errors and we should be able
to do a better job of that than we're doing now. However, doing a better job
would require interpreter surgery that would be too much for emacs-27.
> A mutable object can become constant if it is part of an expression
> that is evaluated
>
> does add some cases not covered by self-evaluating forms, but those are more
> complex cases (e.g. creating forms programmatically and then passing them to
> 'eval'), and then the programmer might justifiably be expected to use their
> head. The self-evaluating forms case is arguably less obvious.
The documentation should not limit itself to self-evaluating forms when
discussing this problem area. Although it's OK for the doc to emphasize
self-evaluating forms, they are not the whole story here.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-02 19:35 ` Paul Eggert
@ 2020-05-03 1:30 ` Dmitry Gutov
2020-05-03 7:40 ` Paul Eggert
0 siblings, 1 reply; 170+ messages in thread
From: Dmitry Gutov @ 2020-05-03 1:30 UTC (permalink / raw)
To: Paul Eggert, Drew Adams
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 02.05.2020 22:35, Paul Eggert wrote:
>> The "objects that appear as a constant" are objects to which exist references
>> from executable code, and where such references are "constant" (or possibly
>> constant, since an implementation might opt not to coalesce the values). That
>> why it's about constant references (and objects to which such references exist).
>
> I don't understand this point.
>
> It sounds like you might be trying to distinguish between constant references
> (i.e., pointers that don't change) and constant objects implemented via
> references (i.e., the pointed-to values don't change).
I'm making a semantic point: these values are special because they are
at the other end of a certain set of "constant references". Not because
they have any other property themselves, like being immutable.
> However, whether the
> references themselves are constant is independent of the issue at hand. The
> issue wouldn't change, for example, if Emacs relocated objects so that
> references were updated regardless of whether the objects' values were constant.
Object relocation is immaterial for the semantics of Elisp. Even if the
objects were relocated from time to time, the references would be
updated, and would point to the same objects again, and thus be constant.
>>> Whether an object is constant is distinct from whether it's derived from a
>>> self-evaluating form, because one can have constants that were never derived
>>> from any self-evaluating form.
>>
>> Examples?
>
> One example is (aset (symbol-name 'car) 0 ?d), which I mentioned a while ago.
> Here's a trickier one:
>
> (let ((constant-string (aref (symbol-function 'error) 1)))
> (aset constant-string 0 183)
> (number-sequence 0 1 0))
>
> This also provokes undefined behavior at the C level while number-sequence is
> doing its thing; my Emacs dumps core, yours may do something different. I'm sure
> there are other examples. The point is that programs should not modify constants.
These two are pretty obviously "undefined behavior", and anybody who
does that have only themselves to blame. So of course it's good to
document this, but since apparently you're not going to fix the semantic
problem currently under discussion yourself, I'm not sure I can keep
this info. You're welcome to re-add it, of course.
> It would be nice if Emacs reliably signaled these errors and we should be able
> to do a better job of that than we're doing now. However, doing a better job
> would require interpreter surgery that would be too much for emacs-27.
Of course.
>> A mutable object can become constant if it is part of an expression
>> that is evaluated
>>
>> does add some cases not covered by self-evaluating forms, but those are more
>> complex cases (e.g. creating forms programmatically and then passing them to
>> 'eval'), and then the programmer might justifiably be expected to use their
>> head. The self-evaluating forms case is arguably less obvious.
>
> The documentation should not limit itself to self-evaluating forms when
> discussing this problem area. Although it's OK for the doc to emphasize
> self-evaluating forms, they are not the whole story here.
The "whole story" can be enumerated in some place, sure. Self-evaluating
forms seem to be the most important area to cover, though.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-03 1:30 ` Dmitry Gutov
@ 2020-05-03 7:40 ` Paul Eggert
2020-05-03 16:44 ` Dmitry Gutov
0 siblings, 1 reply; 170+ messages in thread
From: Paul Eggert @ 2020-05-03 7:40 UTC (permalink / raw)
To: Dmitry Gutov, Drew Adams
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 5/2/20 6:30 PM, Dmitry Gutov wrote:
> I'm making a semantic point: these values are special because they are at the
> other end of a certain set of "constant references". Not because they have any
> other property themselves, like being immutable.
I don't see why this semantic point makes a difference to the user. Regardless
of whether the objects are targets of "constant references" (whatever that
means), programs should not modify the objects in question. And if the semantic
point makes no practical difference, why complicate the manual with it?
It's simpler just to say: programs shouldn't modify these objects.
> The "whole story" can be enumerated in some place, sure. Self-evaluating forms
> seem to be the most important area to cover, though.
They're not the only thing to cover, and attempting to shoehorn this all into
self-evaluating forms could even be misleading.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-03 7:40 ` Paul Eggert
@ 2020-05-03 16:44 ` Dmitry Gutov
2020-05-03 20:48 ` Paul Eggert
0 siblings, 1 reply; 170+ messages in thread
From: Dmitry Gutov @ 2020-05-03 16:44 UTC (permalink / raw)
To: Paul Eggert, Drew Adams
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 03.05.2020 10:40, Paul Eggert wrote:
> It's simpler just to say: programs shouldn't modify these objects.
Which objects, then?
> They're not the only thing to cover, and attempting to shoehorn this all into
> self-evaluating forms could even be misleading.
Which section would that go into? "Constants and Mutability" doesn't work.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-03 16:44 ` Dmitry Gutov
@ 2020-05-03 20:48 ` Paul Eggert
2020-05-03 22:17 ` Dmitry Gutov
2020-05-03 22:18 ` Dmitry Gutov
0 siblings, 2 replies; 170+ messages in thread
From: Paul Eggert @ 2020-05-03 20:48 UTC (permalink / raw)
To: Dmitry Gutov, Drew Adams
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 5/3/20 9:44 AM, Dmitry Gutov wrote:
> On 03.05.2020 10:40, Paul Eggert wrote:
>> It's simpler just to say: programs shouldn't modify these objects.
>
> Which objects, then?
Objects that the documentation currently calls "constants". (If there's a better
term than "constants" we haven't found it yet.)
>> They're not the only thing to cover, and attempting to shoehorn this all into
>> self-evaluating forms could even be misleading.
>
> Which section would that go into? "Constants and Mutability" doesn't work.
If we change the word "constants" to something else, we would presumably retitle
the section and adjust its contents accordingly. Regardless of which word is
chosen we should document the issue, which is broader than that of constants
from self-evaluating forms.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-03 20:48 ` Paul Eggert
@ 2020-05-03 22:17 ` Dmitry Gutov
2020-05-03 22:18 ` Dmitry Gutov
1 sibling, 0 replies; 170+ messages in thread
From: Dmitry Gutov @ 2020-05-03 22:17 UTC (permalink / raw)
To: Paul Eggert, Drew Adams
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 03.05.2020 23:48, Paul Eggert wrote:
> If we change the word "constants" to something else, we would presumably retitle
> the section and adjust its contents accordingly. Regardless of which word is
> chosen we should document the issue, which is broader than that of constants
> from self-evaluating forms.
Yes. But you supposedly want to move some of the contents (which don't
pertain exactly to self-evaluating forms) to some other section.
Could you make that naming choice yourself? I can only move it to one of
the existing ones.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-03 20:48 ` Paul Eggert
2020-05-03 22:17 ` Dmitry Gutov
@ 2020-05-03 22:18 ` Dmitry Gutov
2020-05-03 22:39 ` Paul Eggert
1 sibling, 1 reply; 170+ messages in thread
From: Dmitry Gutov @ 2020-05-03 22:18 UTC (permalink / raw)
To: Paul Eggert, Drew Adams
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 03.05.2020 23:48, Paul Eggert wrote:
> (If there's a better
> term than "constants" we haven't found it yet.)
"Objects referenced from executable code", presumably.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-03 22:18 ` Dmitry Gutov
@ 2020-05-03 22:39 ` Paul Eggert
2020-05-03 22:53 ` Dmitry Gutov
0 siblings, 1 reply; 170+ messages in thread
From: Paul Eggert @ 2020-05-03 22:39 UTC (permalink / raw)
To: Dmitry Gutov, Drew Adams
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 5/3/20 3:18 PM, Dmitry Gutov wrote:
> On 03.05.2020 23:48, Paul Eggert wrote:
>> (If there's a better
>> term than "constants" we haven't found it yet.)
>
> "Objects referenced from executable code", presumably.
A fair number of objects fit that category. (The objects that don't are
typically garbage collected. :-) So that term doesn't describe what we want
clearly and accurately; plus, it's pretty long....
> On 03.05.2020 23:48, Paul Eggert wrote:
>> If we change the word "constants" to something else, we would presumably retitle
>> the section and adjust its contents accordingly. Regardless of which word is
>> chosen we should document the issue, which is broader than that of constants
>> from self-evaluating forms.
>
> Yes. But you supposedly want to move some of the contents (which don't pertain exactly to self-evaluating forms) to some other section.
There must be some miscommunication, as I thought you wanted to move some of
that section's contents. I vaguely recall responding that something along those
lines could work, but I don't recall any specific suggestion after that.
> Could you make that naming choice yourself? I can only move it to one of the existing ones.
I don't understand this request; I don't know what you mean by "it" or by
"moving" or by "existing ones".
If you're talking about the title of the "Constants and Mutability" section, the
current term "constants" is fine with me, as it follows existing practice in
CLtL etc. I'm open for suggestions for changing the term, but we haven't come up
with a better term as far as I can see, or even a term that's roughly equal in
quality.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-03 22:39 ` Paul Eggert
@ 2020-05-03 22:53 ` Dmitry Gutov
2020-05-03 23:10 ` Paul Eggert
0 siblings, 1 reply; 170+ messages in thread
From: Dmitry Gutov @ 2020-05-03 22:53 UTC (permalink / raw)
To: Paul Eggert, Drew Adams
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 04.05.2020 01:39, Paul Eggert wrote:
> A fair number of objects fit that category. (The objects that don't
> are typically garbage collected. So that term doesn't describe what
> we want clearly and accurately; plus, it's pretty long....
Example, please.
> If you're talking about the title of the "Constants and Mutability" section, the
> current term "constants" is fine with me, as it follows existing practice in
> CLtL etc. I'm open for suggestions for changing the term, but we haven't come up
> with a better term as far as I can see, or even a term that's roughly equal in
> quality.
I'm clearly not the only one objecting to the new terms. And especially
the juxtaposition of "constants and mutability" that you added to the
docs. It would be a shame to revert your whole work, though.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-03 22:53 ` Dmitry Gutov
@ 2020-05-03 23:10 ` Paul Eggert
2020-05-04 10:16 ` Dmitry Gutov
0 siblings, 1 reply; 170+ messages in thread
From: Paul Eggert @ 2020-05-03 23:10 UTC (permalink / raw)
To: Dmitry Gutov, Drew Adams
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 5/3/20 3:53 PM, Dmitry Gutov wrote:
> On 04.05.2020 01:39, Paul Eggert wrote:
>> A fair number of objects fit that category. (The objects that don't
>> are typically garbage collected. So that term doesn't describe what
>> we want clearly and accurately; plus, it's pretty long....
>
> Example, please.
The term you used was "Objects referenced from executable code". But that term
includes pretty much every object used in Elisp, at least until the object
becomes unreachable and is garbage-collected.
The concept you were describing is not that general: it's limited to objects
that are part of an expressions that are evaluated. So a better term would be
something like "Objects that are part of expressions that are evaluated" - but
this term is way too long; plus it doesn't accurately describe all the
problematic objects, as there are other reasons that some objects should not be
modified.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-03 23:10 ` Paul Eggert
@ 2020-05-04 10:16 ` Dmitry Gutov
2020-05-04 17:52 ` Paul Eggert
0 siblings, 1 reply; 170+ messages in thread
From: Dmitry Gutov @ 2020-05-04 10:16 UTC (permalink / raw)
To: Paul Eggert, Drew Adams
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 04.05.2020 02:10, Paul Eggert wrote:
> The term you used was "Objects referenced from executable code". But that term
> includes pretty much every object used in Elisp, at least until the object
> becomes unreachable and is garbage-collected.
I see. Could you present a specific counter-example, however?
One where the phrasing "referenced from executable code" would apply,
but "part of expressions that are evaluated" wouldn't.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-04 10:16 ` Dmitry Gutov
@ 2020-05-04 17:52 ` Paul Eggert
2020-05-05 1:39 ` Dmitry Gutov
2020-05-05 20:48 ` Kevin Vigouroux via Bug reports for GNU Emacs, the Swiss army knife of text editors
0 siblings, 2 replies; 170+ messages in thread
From: Paul Eggert @ 2020-05-04 17:52 UTC (permalink / raw)
To: Dmitry Gutov, Drew Adams
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 5/4/20 3:16 AM, Dmitry Gutov wrote:
> On 04.05.2020 02:10, Paul Eggert wrote:
>> The term you used was "Objects referenced from executable code". But that term
>> includes pretty much every object used in Elisp, at least until the object
>> becomes unreachable and is garbage-collected.
>
> I see. Could you present a specific counter-example, however?
>
> One where the phrasing "referenced from executable code" would apply, but "part
> of expressions that are evaluated" wouldn't.
Pretty much any ordinary cons will do. In (let ((x (cons 0 0))) (setcar x 1)),
for example, the cons is referenced from executable code but it's OK to modify
the cons. The cons becomes unreachable when the 'let' finishes. The cons is not
part of any expression that is evaluated.
The problem here evidently is one of terminology, not of understanding the
underlying issues. When I read "Objects referenced from executable code" I
evidently got a different meaning than what you intended. These things happen
when introducing a new terminology.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-04 17:52 ` Paul Eggert
@ 2020-05-05 1:39 ` Dmitry Gutov
2020-05-05 6:09 ` Paul Eggert
2020-05-05 20:48 ` Kevin Vigouroux via Bug reports for GNU Emacs, the Swiss army knife of text editors
1 sibling, 1 reply; 170+ messages in thread
From: Dmitry Gutov @ 2020-05-05 1:39 UTC (permalink / raw)
To: Paul Eggert, Drew Adams
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
[-- Attachment #1: Type: text/plain, Size: 1215 bytes --]
On 04.05.2020 20:52, Paul Eggert wrote:
> Pretty much any ordinary cons will do. In (let ((x (cons 0 0))) (setcar x 1)),
> for example, the cons is referenced from executable code but it's OK to modify
> the cons. The cons becomes unreachable when the 'let' finishes. The cons is not
> part of any expression that is evaluated.
But, I mean, if we just make it a literal:
(let ((x '(0 . 0))) (setcar x 1))
...it also becomes okay to modify it because the cons becomes
unreachable right away. Even so, we strongly recommend against this in
the manual now.
When the form above is a part of a function body, however, then it's
*really* inadvisable to use the latter option.
> The problem here evidently is one of terminology, not of understanding the
> underlying issues. When I read "Objects referenced from executable code" I
> evidently got a different meaning than what you intended. These things happen
> when introducing a new terminology.
I have asked for clarification to try to come up with better phrasing.
But to be frank it's not so important to me as fixing the existing one.
So if you can find a better option, please be my guest.
In the meantime, what do you think about the attached patch?
[-- Attachment #2: no_constants.diff --]
[-- Type: text/x-patch, Size: 16044 bytes --]
diff --git a/doc/lispintro/emacs-lisp-intro.texi b/doc/lispintro/emacs-lisp-intro.texi
index ea16d9ef15..46462162ca 100644
--- a/doc/lispintro/emacs-lisp-intro.texi
+++ b/doc/lispintro/emacs-lisp-intro.texi
@@ -7317,8 +7317,6 @@ setcar
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 @@ setcar
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))
diff --git a/doc/lispref/elisp.texi b/doc/lispref/elisp.texi
index bba1b63115..8abdd6663f 100644
--- a/doc/lispref/elisp.texi
+++ b/doc/lispref/elisp.texi
@@ -297,7 +297,7 @@ Top
* 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.
+* Dangerous Mutations:: Objects which should not be modified.
Programming Types
diff --git a/doc/lispref/eval.texi b/doc/lispref/eval.texi
index baddce4d9c..786c2f2de4 100644
--- a/doc/lispref/eval.texi
+++ b/doc/lispref/eval.texi
@@ -158,11 +158,12 @@ Self-Evaluating Forms
@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
-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}.
+ A self-evaluating form yields a value that becomes part of the
+program, and you should not attempt to modify their contents 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{Dangerous Mutations}.
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 +565,6 @@ Quoting
@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}.
@end defspec
@cindex @samp{'} for quoting
@@ -608,9 +607,9 @@ Quoting
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 new list whereas the latter yields a list
+built from conses that may be shared with other values.
+@xref{Self-Evaluating Forms}.
Other quoting constructs include @code{function} (@pxref{Anonymous
Functions}), which causes an anonymous lambda expression written in Lisp
@@ -710,7 +709,7 @@ Backquote
@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,
+splices, it acts like @code{quote} in that it yields conses,
vectors and strings that should not be modified.
@node Eval
diff --git a/doc/lispref/lists.texi b/doc/lispref/lists.texi
index fcaf4386b1..065853042a 100644
--- a/doc/lispref/lists.texi
+++ b/doc/lispref/lists.texi
@@ -866,15 +866,14 @@ List Variables
@node Modifying Lists
@section Modifying Existing List Structure
@cindex destructive list operations
-@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 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}.
+Destructive operations should be applied only to lists constructed via
+@code{cons}, @code{list} or similar operations. Lists created by
+quoting are part of the program and should not be changed by destructive
+operations. @xref{Dangerous Mutations}.
@cindex CL note---@code{rplaca} vs @code{setcar}
@quotation
@@ -911,7 +910,7 @@ Setcar
@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 +930,7 @@ Setcar
@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 +1021,11 @@ Setcdr
@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 +1134,11 @@ Rearrangement
@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
@@ -1168,7 +1167,7 @@ Rearrangement
@end group
@end example
-However, the other arguments (all but the last) should be mutable lists.
+However, the other arguments (all but the last) must be lists.
A common pitfall is to use a constant list as a non-last
argument to @code{nconc}. If you do this, the resulting behavior
diff --git a/doc/lispref/objects.texi b/doc/lispref/objects.texi
index 1d5b2c690f..9fdcb4b1bc 100644
--- a/doc/lispref/objects.texi
+++ b/doc/lispref/objects.texi
@@ -46,10 +46,6 @@ Lisp Data Types
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 @@ 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.
+* Dangerous Mutations:: Objects which should not be modified.
@end menu
@node Printed Representation
@@ -2379,51 +2375,34 @@ Equality Predicates
@end example
@end defun
-@node Constants and Mutability
-@section Constants and Mutability
-@cindex constants
-@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.
-
- 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.
+@node Dangerous Mutations
+@section Dangerous Mutations
- 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}.
+ Most Lisp programs first create some values, then mutate them. For
+this to work well, a new value should generally be created every time
+a function is called. When a value is created using a function such
+as @code{list}, @code{cons}, @code{make-string} or
+@code{copy-sequence}, that happens reliably, and such a value is safe
+to modify.
- 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.
+ Modifying the values obtained by evaluating a self-evaluating form
+(such as @code{"abc"}) is not advised. Values that appear as part of
+a program should not be modified.
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.
-
- When the same constant occurs multiple times in a program, the Lisp
-interpreter might save time or space by reusing existing constants or
-constant components. For example, @code{(eq "abc" "abc")} returns
+(@pxref{Constant Variables}). The current version of Emacs might not
+signal an error when a dangerous mutation occurs, however. The result
+is essentially 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. If a misbehaving program tries
+to change such a value then it might actually succeed, or the program
+might crash or worse. This will hopefully be improved in future
+versions of Emacs.
+
+ When the same literal occurs multiple times in a program, the Lisp
+interpreter might save time or space by reusing existing values or
+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
-instances. Lisp programs should be written so that they work
-regardless of whether this optimization is in use.
+@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.
diff --git a/doc/lispref/sequences.texi b/doc/lispref/sequences.texi
index 1cb0d05cc7..e41ce2ebe2 100644
--- a/doc/lispref/sequences.texi
+++ b/doc/lispref/sequences.texi
@@ -183,11 +183,11 @@ Sequence Functions
@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 @@ Sequence Functions
@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 @@ Sequence Functions
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]
@@ -330,7 +330,7 @@ Sequence Functions
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.
+encouraged to treat strings as immutable.
@end defun
@@ -374,7 +374,7 @@ Sequence Functions
@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 +1228,7 @@ Array Functions
@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 +1237,7 @@ Array Functions
@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,10 +1247,6 @@ Array Functions
@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}.
-
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.
@@ -1262,7 +1258,6 @@ Array Functions
@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 +1266,6 @@ Array Functions
@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 ?-)
@@ -1309,9 +1303,7 @@ Vectors
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.
-@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}.
+@xref{Self-Evaluating Forms}.
Here are examples illustrating these principles:
diff --git a/doc/lispref/strings.texi b/doc/lispref/strings.texi
index a4c9c2549c..3a6de56584 100644
--- a/doc/lispref/strings.texi
+++ b/doc/lispref/strings.texi
@@ -51,8 +51,7 @@ String Basics
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}).
+and @code{aset} (@pxref{Array Functions}).
There are two text representations for non-@acronym{ASCII}
characters in Emacs strings (and in buffers): unibyte and multibyte.
@@ -383,8 +382,8 @@ Modifying Strings
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}.
+operations to alter the contents of a string literal.
+@xref{Dangerous Mutations}.
The most basic way to alter the contents of an existing string is with
@code{aset} (@pxref{Array Functions}). @code{(aset @var{string}
^ permalink raw reply related [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-05 1:39 ` Dmitry Gutov
@ 2020-05-05 6:09 ` Paul Eggert
2020-05-05 12:38 ` Dmitry Gutov
2020-05-05 17:40 ` Drew Adams
0 siblings, 2 replies; 170+ messages in thread
From: Paul Eggert @ 2020-05-05 6:09 UTC (permalink / raw)
To: Dmitry Gutov, Drew Adams
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 5/4/20 6:39 PM, Dmitry Gutov wrote:
> if we just make it a literal:
>
> (let ((x '(0 . 0))) (setcar x 1))
>
> ...it also becomes okay to modify it
No, because the literal might be placed in read-only storage of some sort.
> In the meantime, what do you think about the attached patch?
Most of it is OK, but it goes too far in removing useful practical advice about
not doing "dangerous mutations" (to use the terminology you prefer). The defspec
for quote, the defuns for aset, setcar and setcdr, and the square-bracket
notation for vectors, should all point to the Dangerous Mutations section.
Also, the section on Dangerous Mutations should not imply that self-evaluating
forms are the only way to get objects that are dangerous to mutate, as there are
other ways to get such objects.
The section Dangerous Mutations is really about Mutations, not merely about
Dangerous Mutations. For example, it talks about modifying constant variables.
So I suggest changing its name to just "Mutations". This will help us in future
versions of Emacs, in which at least some of these mutations should become
non-dangerous.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-05 6:09 ` Paul Eggert
@ 2020-05-05 12:38 ` Dmitry Gutov
2020-05-09 6:10 ` Paul Eggert
2020-05-05 17:40 ` Drew Adams
1 sibling, 1 reply; 170+ messages in thread
From: Dmitry Gutov @ 2020-05-05 12:38 UTC (permalink / raw)
To: Paul Eggert, Drew Adams
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 05.05.2020 09:09, Paul Eggert wrote:
>> In the meantime, what do you think about the attached patch?
>
> Most of it is OK, but it goes too far in removing useful practical advice about
> not doing "dangerous mutations" (to use the terminology you prefer). The defspec
> for quote, the defuns for aset, setcar and setcdr, and the square-bracket
> notation for vectors, should all point to the Dangerous Mutations section.
I think that was too much: we've been living with this problem for many
years without hitting it too often. Sticking warning all over seems like
an overreaction.
> Also, the section on Dangerous Mutations should not imply that self-evaluating
> forms are the only way to get objects that are dangerous to mutate, as there are
> other ways to get such objects.
I thought your explanation was a bit too vague, so I added concreteness.
In essence though it was saying constants this and constants that, but
the actual examples were also only about self-evaluating forms. Did I
delete some informative part?
> The section Dangerous Mutations is really about Mutations, not merely about
> Dangerous Mutations. For example, it talks about modifying constant variables.
> So I suggest changing its name to just "Mutations". This will help us in future
> versions of Emacs, in which at least some of these mutations should become
> non-dangerous.
It's talking about the cases where a modification shouldn't occur, hence
the name. When something from the list becomes legal, I think this
section will just stop mentioning it?
In any case, none of my objections here are strong ones. How about you
take the proposed patch and update it as you see fit? As long as
"constant values" don't make a comeback, I'm good.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-05 6:09 ` Paul Eggert
2020-05-05 12:38 ` Dmitry Gutov
@ 2020-05-05 17:40 ` Drew Adams
2020-05-05 18:49 ` Dmitry Gutov
1 sibling, 1 reply; 170+ messages in thread
From: Drew Adams @ 2020-05-05 17:40 UTC (permalink / raw)
To: Paul Eggert, Dmitry Gutov
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
Apologies for chiming in here again.
And I haven't read the proposed text or
followed the thread recently.
But I just saw "Dangerous Mutations".
I really don't think that it's helpful or
appropriate to speak of danger in the context
of the gotcha we've been discussing.
Danger is danger. Yes, with undefined behavior,
and with possible modification of list structure
etc., there is the possibility of loss of data,
and that's not a good thing. Undefined is scary.
But I'm not in favor of crying "DANGER" about
such things. At all.
Check the Common Lisp doc. You don't find
such screaming warnings plastered throughout,
whenever it comes to destructive modification.
The word "destructive" is sufficiently strong.
And in the case of the gotchas being discussed
it's not necessarily even destructive
modification. The unknown/undefined is just
that. No need (and inappropriate) to wrap it
DANGEROUS!
Just one opinion.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-05 17:40 ` Drew Adams
@ 2020-05-05 18:49 ` Dmitry Gutov
2020-05-05 19:26 ` Drew Adams
0 siblings, 1 reply; 170+ messages in thread
From: Dmitry Gutov @ 2020-05-05 18:49 UTC (permalink / raw)
To: Drew Adams, Paul Eggert
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
On 05.05.2020 20:40, Drew Adams wrote:
> The word "destructive" is sufficiently strong.
> And in the case of the gotchas being discussed
> it's not necessarily even destructive
> modification.
It's not modification if it's not destructive. At least, in the context
of the problem we're trying to describe.
Destructive modification, by itself, is a very regular occasion. Not
something to warn against.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-05 18:49 ` Dmitry Gutov
@ 2020-05-05 19:26 ` Drew Adams
0 siblings, 0 replies; 170+ messages in thread
From: Drew Adams @ 2020-05-05 19:26 UTC (permalink / raw)
To: Dmitry Gutov, Paul Eggert
Cc: Michael Heerdegen, Mattias Engdegård, ke.vigouroux, 40671,
Richard Stallman
> It's not modification if it's not destructive. At least, in the context
> of the problem we're trying to describe.
>
> Destructive modification, by itself, is a very regular occasion. Not
> something to warn against.
Whatever. My point is that there's no need to
scream "Danger!". A warning does not imply
danger. And a tip about a gotcha is not
necessarily even a warning.
Can the consequences ever be awful? Presumably.
Will they often be awful? Not likely.
The most likely negative effect is spending
time trying to figure out what's happening.
That's why we should have a tip about the
gotcha.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-04 17:52 ` Paul Eggert
2020-05-05 1:39 ` Dmitry Gutov
@ 2020-05-05 20:48 ` Kevin Vigouroux via Bug reports for GNU Emacs, the Swiss army knife of text editors
2020-05-09 5:57 ` Paul Eggert
1 sibling, 1 reply; 170+ messages in thread
From: Kevin Vigouroux via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2020-05-05 20:48 UTC (permalink / raw)
To: Paul Eggert
Cc: Richard Stallman, Michael Heerdegen, Mattias Engdegård,
Dmitry Gutov, Drew Adams, 40671
Paul Eggert <eggert@cs.ucla.edu> writes:
> On 5/4/20 3:16 AM, Dmitry Gutov wrote:
>> On 04.05.2020 02:10, Paul Eggert wrote:
>>> The term you used was "Objects referenced from executable code". But that term
>>> includes pretty much every object used in Elisp, at least until the object
>>> becomes unreachable and is garbage-collected.
>>
>> I see. Could you present a specific counter-example, however?
>>
>> One where the phrasing "referenced from executable code" would apply, but "part
>> of expressions that are evaluated" wouldn't.
>
> Pretty much any ordinary cons will do. In (let ((x (cons 0 0))) (setcar x 1)),
> for example, the cons is referenced from executable code but it's OK to modify
> the cons. The cons becomes unreachable when the 'let' finishes. The cons is not
> part of any expression that is evaluated.
>
> The problem here evidently is one of terminology, not of understanding the
> underlying issues. When I read "Objects referenced from executable code" I
> evidently got a different meaning than what you intended. These things happen
> when introducing a new terminology.
Would the expression "constant form" be appropriate? Here is the
definition given in the CLHS (in the glossary).
Constant form: Any form for which evaluation always yields the same
value, that neither affects nor is affected by the environment in which
it is evaluated (except that is permitted to refer to the names of
constant variables defined in the environment), and that neither affects
nor is affected by the state of any object except those objects that are
otherwise inaccessible parts of objects created by the form
itself. For instance, a car form in which the argument is a quote form is a
constant form.
If I understand correctly, the problem is partially related to self-modifying code.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-05 20:48 ` Kevin Vigouroux via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2020-05-09 5:57 ` Paul Eggert
0 siblings, 0 replies; 170+ messages in thread
From: Paul Eggert @ 2020-05-09 5:57 UTC (permalink / raw)
To: Kevin Vigouroux
Cc: 40671, Michael Heerdegen, Mattias Engdegård, Dmitry Gutov,
Richard Stallman
On 5/5/20 1:48 PM, Kevin Vigouroux wrote:
> Would the expression "constant form" be appropriate?
Not exactly, as that refers to a form in the source code, whereas we are talking
about objects available at run-time. There is overlap between the two concepts
but some objects are "constant" (in the sense of the current emacs-27 doc)
without appearing in the source code.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-05 12:38 ` Dmitry Gutov
@ 2020-05-09 6:10 ` Paul Eggert
2020-05-10 3:13 ` Dmitry Gutov
0 siblings, 1 reply; 170+ messages in thread
From: Paul Eggert @ 2020-05-09 6:10 UTC (permalink / raw)
To: Dmitry Gutov
Cc: ke.vigouroux, 40671, Michael Heerdegen, Mattias Engdegård,
Richard Stallman
[-- Attachment #1: Type: text/plain, Size: 627 bytes --]
On 5/5/20 5:38 AM, Dmitry Gutov wrote:
> In any case, none of my objections here are strong ones. How about you take the
> proposed patch and update it as you see fit? As long as "constant values" don't
> make a comeback, I'm good.
OK, attached is a draft patch to emacs-27. Although it doesn't go as far as your
patch, it does keep some of it, and in particular it gets rid of the
introduction of the term "constant" to describe objects that should not be
changed. It also omits the "Dangerous" that Drew objected to, and gives an
example of a term that was formerly mutable but is now something that you should
not change.
[-- Attachment #2: 0001-Don-t-use-constant-for-values-you-shouldn-t-change.txt --]
[-- Type: text/plain, Size: 17465 bytes --]
From 702f28be9beea4a0475094140afb85cd4aa366ba Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Fri, 8 May 2020 22:53:41 -0700
Subject: [PATCH] =?UTF-8?q?Don=E2=80=99t=20use=20=E2=80=9Cconstant?=
=?UTF-8?q?=E2=80=9D=20for=20values=20you=20shouldn=E2=80=99t=20change?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Inspired by patch proposed by Dmitry Gutov (Bug#40671#393).
* 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.
---
doc/lispintro/emacs-lisp-intro.texi | 5 +-
doc/lispref/elisp.texi | 2 +-
doc/lispref/eval.texi | 21 +++++----
doc/lispref/lists.texi | 16 +++----
doc/lispref/objects.texi | 71 +++++++++++++----------------
doc/lispref/sequences.texi | 25 +++++-----
doc/lispref/strings.texi | 11 ++---
7 files changed, 68 insertions(+), 83 deletions(-)
diff --git a/doc/lispintro/emacs-lisp-intro.texi b/doc/lispintro/emacs-lisp-intro.texi
index ea16d9ef15..46462162ca 100644
--- a/doc/lispintro/emacs-lisp-intro.texi
+++ b/doc/lispintro/emacs-lisp-intro.texi
@@ -7317,8 +7317,6 @@ setcar
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 @@ setcar
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))
diff --git a/doc/lispref/elisp.texi b/doc/lispref/elisp.texi
index bba1b63115..9a6796790c 100644
--- a/doc/lispref/elisp.texi
+++ b/doc/lispref/elisp.texi
@@ -297,7 +297,7 @@ Top
* 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
diff --git a/doc/lispref/eval.texi b/doc/lispref/eval.texi
index baddce4d9c..39f342a798 100644
--- a/doc/lispref/eval.texi
+++ b/doc/lispref/eval.texi
@@ -158,11 +158,11 @@ Self-Evaluating Forms
@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 @@ Quoting
@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 @@ Quoting
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 @@ Backquote
@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
diff --git a/doc/lispref/lists.texi b/doc/lispref/lists.texi
index fcaf4386b1..ae793d5e15 100644
--- a/doc/lispref/lists.texi
+++ b/doc/lispref/lists.texi
@@ -873,8 +873,8 @@ Modifying Lists
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 @@ Setcar
@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 @@ Setcar
@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 @@ Setcdr
@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 @@ Rearrangement
@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
diff --git a/doc/lispref/objects.texi b/doc/lispref/objects.texi
index 1d5b2c690f..a0afadc2d7 100644
--- a/doc/lispref/objects.texi
+++ b/doc/lispref/objects.texi
@@ -46,10 +46,6 @@ Lisp Data Types
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 @@ 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.
@end menu
@node Printed Representation
@@ -2379,51 +2375,48 @@ Equality Predicates
@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, you can create
+a new number by calculating one, but you cannot modify 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
+ Although numbers never change and all markers are mutable, a type
+can be a hybrid with some members mutable and other members not. These
types include conses, vectors, strings, and symbols. For example, the string
-literal @code{"aaa"} yields a constant string, whereas the function
+literal @code{"aaa"} yields a string that should not be changed, whereas the
call @code{(make-string 3 ?a)} yields a mutable string that can be
changed via later calls to @code{aset}.
- 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, in @code{(eval (list 'quote (list 1)))}
+the list @code{(1)} was mutable when it was created, but it should not
+be changed after it was part of an argument to @code{eval}. The
+reverse does not occur: an object that should not be changed never
+becomes mutable afterwards.
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.
-
- When the same constant occurs multiple times in a program, the Lisp
-interpreter might save time or space by reusing existing constants or
-constant components. For example, @code{(eq "abc" "abc")} returns
+If a program attempts to change other 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 the same value appears multiple times in a program, the Lisp
+interpreter might save time or space by reusing existing values or
+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.
diff --git a/doc/lispref/sequences.texi b/doc/lispref/sequences.texi
index 1cb0d05cc7..91c3049f87 100644
--- a/doc/lispref/sequences.texi
+++ b/doc/lispref/sequences.texi
@@ -183,11 +183,11 @@ Sequence Functions
@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 @@ Sequence Functions
@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 @@ Sequence Functions
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 @@ Sequence Functions
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 @@ Sequence Functions
@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 @@ Array Functions
@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 @@ Array Functions
@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 @@ Array Functions
@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 @@ Array Functions
@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 @@ Array Functions
@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 @@ Vectors
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:
diff --git a/doc/lispref/strings.texi b/doc/lispref/strings.texi
index a4c9c2549c..70c3b3cf4b 100644
--- a/doc/lispref/strings.texi
+++ b/doc/lispref/strings.texi
@@ -49,10 +49,9 @@ String Basics
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 @@ 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.
-@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}
--
2.17.1
^ permalink raw reply related [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-09 6:10 ` Paul Eggert
@ 2020-05-10 3:13 ` Dmitry Gutov
2020-05-10 13:34 ` Dmitry Gutov
2020-05-10 17:29 ` Paul Eggert
0 siblings, 2 replies; 170+ messages in thread
From: Dmitry Gutov @ 2020-05-10 3:13 UTC (permalink / raw)
To: Paul Eggert
Cc: ke.vigouroux, 40671, Michael Heerdegen, Mattias Engdegård,
Richard Stallman
Hi Paul,
On 09.05.2020 09:10, Paul Eggert wrote:
> On 5/5/20 5:38 AM, Dmitry Gutov wrote:
>
>> In any case, none of my objections here are strong ones. How about you take the
>> proposed patch and update it as you see fit? As long as "constant values" don't
>> make a comeback, I'm good.
> OK, attached is a draft patch to emacs-27. Although it doesn't go as far as your
> patch, it does keep some of it, and in particular it gets rid of the
> introduction of the term "constant" to describe objects that should not be
> changed. It also omits the "Dangerous" that Drew objected to, and gives an
> example of a term that was formerly mutable but is now something that you should
> not change.
It's an improvement, but still I don't understand your choice.
Starting with:
Some Lisp objects should never change. For example, you can create
a new number by calculating one, but you cannot modify the value of an
existing number.
You start talking about objects that "should [not] change". And give an
example of an object that _cannot_ change.
Then, this passage is still confusing, and it doesn't have to be:
Although numbers never change and all markers are mutable, a type
can be a hybrid with some members mutable and other members not.
I could understand it if it was describing an existing type system of
the language, or implementation internals, but this is a purely
imaginary type system. Why make the mental image harder than we have to?
Further down:
A mutable object stops being mutable if it is part of an expression
that is evaluated. For example,
in @code{(eval (list 'quote (list 1)))}
the list @code{(1)} was mutable when it was created, but it should not
be changed after it was part of an argument to @code{eval}.
But the list object didn't change, just an outside reference to its head
was created, and that made it "possibly shared", depending on how the
aggregated value is subsequently used.
And further:
...whereas the
call @code{(make-string 3 ?a)} yields a mutable string that can be
changed via later calls to @code{aset}
The opposite of "mutable" is "immutable". Are quoted strings immutable?
They are not.
Overall the phrase "that might be shared" is a good replacement. Why not
keep to it? The rest of the patch doesn't try so hard to force the new
definitions anymore, so your new meaning of "mutable" doesn't seem
indispensable.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-10 3:13 ` Dmitry Gutov
@ 2020-05-10 13:34 ` Dmitry Gutov
2020-05-10 17:29 ` Paul Eggert
1 sibling, 0 replies; 170+ messages in thread
From: Dmitry Gutov @ 2020-05-10 13:34 UTC (permalink / raw)
To: Paul Eggert
Cc: Michael Heerdegen, ke.vigouroux, 40671, Mattias Engdegård,
Richard Stallman
On 10.05.2020 06:13, Dmitry Gutov wrote:
> The opposite of "mutable" is "immutable". Are quoted strings immutable?
^ string literals
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-10 3:13 ` Dmitry Gutov
2020-05-10 13:34 ` Dmitry Gutov
@ 2020-05-10 17:29 ` Paul Eggert
2020-05-11 0:00 ` Michael Heerdegen
2020-05-11 0:44 ` Dmitry Gutov
1 sibling, 2 replies; 170+ messages in thread
From: Paul Eggert @ 2020-05-10 17:29 UTC (permalink / raw)
To: Dmitry Gutov
Cc: ke.vigouroux, 40671, Michael Heerdegen, Mattias Engdegård,
Richard Stallman
[-- Attachment #1: Type: text/plain, Size: 2025 bytes --]
On 5/9/20 8:13 PM, Dmitry Gutov wrote:
> You start talking about objects that "should [not] change". And give an example
> of an object that _cannot_ change.
That's easily altered to also give an example of an object that should not
change; see attached patch.
> I could understand it if it was describing an existing type system of the
> language, or implementation internals, but this is a purely imaginary type
> system.
objects.texi already talks about the Emacs Lisp type system and specifically
mentions strings, conses, etc. as types. Even if one considers the Emacs Lisp
type system to be "imaginary", it's reasonable to use the documentation's
already-existing terminology here.
> the list object didn't change, just an outside reference to its head was
> created,
The attached patch alters the example so that the list object does change (or at
least tries to).
> The opposite of "mutable" is "immutable". Are string literals immutable? They are
> not.
They might be mutable, and they might not be. The documentation deliberately
doesn't say, because we don't want to document the details (they have changed in
the past and are likely to change in the future).
> Overall the phrase "that might be shared" is a good replacement. Why not keep to
> it?
Because it's not an accurate statement of the problem. The set of objects that
might be shared differs from the set of objects that should not change. The
Mutability node focuses on the latter set of objects, and gives the former as an
example but it is not the only sort of object that should not change.
> your new meaning of "mutable" doesn't seem indispensable.
That bar is too high, as hardly anything in the manual is *indispensable*. Ihe
notion of mutability is good to have in the manual, as it reduces confusion and
helps in documentation elsewhere. That's good enough.
I'm attaching two patches. The first are the changes mentioned above, and the
second is a single patch that combines the first patch with the changes I
previously proposed.
[-- Attachment #2: 0001-Update-mutability-doc.patch --]
[-- Type: text/x-patch, Size: 3026 bytes --]
From f2f7cff7c72ca399ca49a50ceac660c3b0991d92 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Sun, 10 May 2020 10:01:46 -0700
Subject: [PATCH] Update mutability doc
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* doc/lispref/objects.texi (Mutability): Revise in response
to Dmitry Gutov’s comments (Bug#40671#420).
---
doc/lispref/objects.texi | 33 ++++++++++++++++++++++-----------
1 file changed, 22 insertions(+), 11 deletions(-)
diff --git a/doc/lispref/objects.texi b/doc/lispref/objects.texi
index a0afadc2d7..7727a630dd 100644
--- a/doc/lispref/objects.texi
+++ b/doc/lispref/objects.texi
@@ -2379,26 +2379,37 @@ Mutability
@section Mutability
@cindex mutable objects
- Some Lisp objects should never change. For example, you can create
-a new number by calculating one, but you cannot modify the value of an
-existing number.
+ 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 @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 numbers never change and all markers are mutable, a type
-can be a hybrid with some members mutable and other members not. These
-types include conses, vectors, strings, and symbols. For example, the string
-literal @code{"aaa"} yields a string that should not be changed, whereas the
-call @code{(make-string 3 ?a)} yields a mutable string that can be
+ 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, strings, and symbols. 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}.
A mutable object stops being mutable if it is part of an expression
-that is evaluated. For example, in @code{(eval (list 'quote (list 1)))}
-the list @code{(1)} was mutable when it was created, but it should not
-be changed after it was part of an argument to @code{eval}. The
+that is evaluated. For example:
+
+@example
+(let* ((x (list 0.5))
+ (y (eval (list 'quote x))))
+ (setcar x 1.5) ;; The program should not do this.
+ y)
+@end example
+
+@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.
--
2.17.1
[-- Attachment #3: 0001-Don-t-use-constant-for-values-you-shouldn-t-change.patch --]
[-- Type: text/x-patch, Size: 18509 bytes --]
From 1ddbbfd38c280822d1bed3c1281909fbfea1f54f Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Sun, 10 May 2020 09:27:02 -0700
Subject: [PATCH] =?UTF-8?q?Don=E2=80=99t=20use=20=E2=80=9Cconstant?=
=?UTF-8?q?=E2=80=9D=20for=20values=20you=20shouldn=E2=80=99t=20change?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Inspired by patch proposed by Dmitry Gutov (Bug#40671#393)
and by his further comments (Bug#40671#420).
* 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.
Update mutability doc
* doc/lispref/objects.texi (Mutability): Revise in response
to Dmitry Gutov’s comments (Bug#40671#420).
---
doc/lispintro/emacs-lisp-intro.texi | 5 +-
doc/lispref/elisp.texi | 2 +-
doc/lispref/eval.texi | 21 +++----
doc/lispref/lists.texi | 16 ++---
doc/lispref/objects.texi | 90 +++++++++++++++--------------
doc/lispref/sequences.texi | 25 ++++----
doc/lispref/strings.texi | 11 ++--
7 files changed, 83 insertions(+), 87 deletions(-)
diff --git a/doc/lispintro/emacs-lisp-intro.texi b/doc/lispintro/emacs-lisp-intro.texi
index ea16d9ef15..46462162ca 100644
--- a/doc/lispintro/emacs-lisp-intro.texi
+++ b/doc/lispintro/emacs-lisp-intro.texi
@@ -7317,8 +7317,6 @@ setcar
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 @@ setcar
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))
diff --git a/doc/lispref/elisp.texi b/doc/lispref/elisp.texi
index bba1b63115..9a6796790c 100644
--- a/doc/lispref/elisp.texi
+++ b/doc/lispref/elisp.texi
@@ -297,7 +297,7 @@ Top
* 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
diff --git a/doc/lispref/eval.texi b/doc/lispref/eval.texi
index baddce4d9c..39f342a798 100644
--- a/doc/lispref/eval.texi
+++ b/doc/lispref/eval.texi
@@ -158,11 +158,11 @@ Self-Evaluating Forms
@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 @@ Quoting
@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 @@ Quoting
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 @@ Backquote
@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
diff --git a/doc/lispref/lists.texi b/doc/lispref/lists.texi
index fcaf4386b1..ae793d5e15 100644
--- a/doc/lispref/lists.texi
+++ b/doc/lispref/lists.texi
@@ -873,8 +873,8 @@ Modifying Lists
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 @@ Setcar
@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 @@ Setcar
@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 @@ Setcdr
@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 @@ Rearrangement
@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
diff --git a/doc/lispref/objects.texi b/doc/lispref/objects.texi
index 1d5b2c690f..7727a630dd 100644
--- a/doc/lispref/objects.texi
+++ b/doc/lispref/objects.texi
@@ -46,10 +46,6 @@ Lisp Data Types
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 @@ 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.
@end menu
@node Printed Representation
@@ -2379,51 +2375,59 @@ Equality Predicates
@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.
-
- 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.
-
- 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
+ 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 @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 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, strings, and symbols. 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}.
- 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:
+
+@example
+(let* ((x (list 0.5))
+ (y (eval (list 'quote x))))
+ (setcar x 1.5) ;; The program should not do this.
+ y)
+@end example
+
+@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.
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.
-
- When the same constant occurs multiple times in a program, the Lisp
-interpreter might save time or space by reusing existing constants or
-constant components. For example, @code{(eq "abc" "abc")} returns
+If a program attempts to change other 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 the same value appears multiple times in a program, the Lisp
+interpreter might save time or space by reusing existing values or
+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.
diff --git a/doc/lispref/sequences.texi b/doc/lispref/sequences.texi
index 1cb0d05cc7..91c3049f87 100644
--- a/doc/lispref/sequences.texi
+++ b/doc/lispref/sequences.texi
@@ -183,11 +183,11 @@ Sequence Functions
@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 @@ Sequence Functions
@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 @@ Sequence Functions
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 @@ Sequence Functions
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 @@ Sequence Functions
@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 @@ Array Functions
@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 @@ Array Functions
@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 @@ Array Functions
@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 @@ Array Functions
@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 @@ Array Functions
@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 @@ Vectors
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:
diff --git a/doc/lispref/strings.texi b/doc/lispref/strings.texi
index a4c9c2549c..70c3b3cf4b 100644
--- a/doc/lispref/strings.texi
+++ b/doc/lispref/strings.texi
@@ -49,10 +49,9 @@ String Basics
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 @@ 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.
-@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}
--
2.17.1
^ permalink raw reply related [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-10 17:29 ` Paul Eggert
@ 2020-05-11 0:00 ` Michael Heerdegen
2020-05-11 0:26 ` Dmitry Gutov
` (2 more replies)
2020-05-11 0:44 ` Dmitry Gutov
1 sibling, 3 replies; 170+ messages in thread
From: Michael Heerdegen @ 2020-05-11 0:00 UTC (permalink / raw)
To: Paul Eggert
Cc: Mattias Engdegård, Dmitry Gutov, 40671, Richard Stallman,
ke.vigouroux
Paul Eggert <eggert@cs.ucla.edu> writes:
> I'm attaching two patches.
Thanks for the continued work on this, I appreciate the improvements and
the general direction. I may have missed parts of the discussion
recently, sorry if some comments are unsubstantial.
So, a few questions about the patches:
> + 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, strings, and symbols. 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}.
Is this a good statement? The string read syntax, and the syntax for
lists makes it easy to make such objects part of a program. But all
classes of objects you call mutable can end up as part of a program.
Are there any classes of "types" where all members are always mutable?
Second point: you mix up objects vs. object evaluation. For conses you
speak about the objects, for symbols about the binding (i.e. the result
of the evaluation). Conses can also be evaluated (most programs are
conses), but that's surely not what you want to describe. I would not
say symbols are mutable. Symbols are constant AFAICT, their bindings
are not (variables are not constant).
> + A mutable object stops being mutable if it is part of an expression
> +that is evaluated. For example:
FWIW, I would feel better about the word "mutable" if you would
introduce the term like "safely mutable", and then say that we call it
just "mutable" in the following sections because this is shorter. Drew
mentioned his dislike for the term "safe" AFAIR but I think "my Emacs
won't crash if I follow this" vs. "it can crash" describes some kind of
safety. Ignore if this comment is irrelevant because this is already
done or treated otherwise.
> + When the same value appears multiple times in a program, the Lisp
> +interpreter might save time or space by reusing existing values or
> +their components. For example, @code{(eq "abc" "abc")} returns
I think we call "values" what evaluation of expressions yields, so
values don't appear in a program (to be read). I don't know the
backgrounds and when this can happen. Is it always the interpreter that
does this mapping?
"Same syntax" is not good as well:
(eq (list 1 2 3) (list 1 2 3))
doesn't provoke the pitfall you warn about, but your wording doesn't
make clear why the one case is ok and the other is not. Maybe it's
again as simple as saying something about objects as being part of a
program?
Thanks again,
Michael.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-11 0:00 ` Michael Heerdegen
@ 2020-05-11 0:26 ` Dmitry Gutov
2020-05-11 1:47 ` Drew Adams
2020-05-11 1:53 ` Paul Eggert
2 siblings, 0 replies; 170+ messages in thread
From: Dmitry Gutov @ 2020-05-11 0:26 UTC (permalink / raw)
To: Michael Heerdegen, Paul Eggert
Cc: ke.vigouroux, 40671, Richard Stallman, Mattias Engdegård
Thanks, Michael,
+1 on your points, but this one especially:
On 11.05.2020 03:00, Michael Heerdegen wrote:
>> + A mutable object stops being mutable if it is part of an expression
>> +that is evaluated. For example:
>
> FWIW, I would feel better about the word "mutable" if you would
> introduce the term like "safely mutable", and then say that we call it
> just "mutable" in the following sections because this is shorter. Drew
> mentioned his dislike for the term "safe" AFAIR but I think "my Emacs
> won't crash if I follow this" vs. "it can crash" describes some kind of
> safety.
"safely mutable" definitely sounds better to me. And while we might use
the shorthand "mutable" in the corresponding section, while referring to
this notion outside of it, it would be better to use the full two-word
version.
>> + When the same value appears multiple times in a program, the Lisp
>> +interpreter might save time or space by reusing existing values or
>> +their components. For example, @code{(eq "abc" "abc")} returns
>
> I think we call "values" what evaluation of expressions yields, so
> values don't appear in a program (to be read). I don't know the
> backgrounds and when this can happen. Is it always the interpreter that
> does this mapping?
>
> "Same syntax" is not good as well:
>
> (eq (list 1 2 3) (list 1 2 3))
>
> doesn't provoke the pitfall you warn about, but your wording doesn't
> make clear why the one case is ok and the other is not. Maybe it's
> again as simple as saying something about objects as being part of a
> program?
FWIW, CLtL seems to use a clunky term "similar as constants" for this.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-10 17:29 ` Paul Eggert
2020-05-11 0:00 ` Michael Heerdegen
@ 2020-05-11 0:44 ` Dmitry Gutov
2020-05-11 1:57 ` Paul Eggert
1 sibling, 1 reply; 170+ messages in thread
From: Dmitry Gutov @ 2020-05-11 0:44 UTC (permalink / raw)
To: Paul Eggert
Cc: ke.vigouroux, 40671, Michael Heerdegen, Mattias Engdegård,
Richard Stallman
On 10.05.2020 20:29, Paul Eggert wrote:
> On 5/9/20 8:13 PM, Dmitry Gutov wrote:
>
>> You start talking about objects that "should [not] change". And give an example
>> of an object that _cannot_ change.
>
> That's easily altered to also give an example of an object that should not
> change; see attached patch.
Quoting the new paragraph. Now it goes "should not" -> "cannot":
+ 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.
"Indeed"?
>> I could understand it if it was describing an existing type system of the
>> language, or implementation internals, but this is a purely imaginary type
>> system.
>
> objects.texi already talks about the Emacs Lisp type system and specifically
> mentions strings, conses, etc. as types. Even if one considers the Emacs Lisp
> type system to be "imaginary", it's reasonable to use the documentation's
> already-existing terminology here.
Strings, conses, etc, are anything but imaginary (try using one in a
function that expects another, and you'll almost always get a runtime
error). The changing "mutability" status is imaginary, however.
This also requires the reader to read the manual without missing a
reference. A regular person would not understand your meaning of
"mutable" without following the reference to {Mutability}. Which not
everybody is going to do, and which is harder to do when reading a
printed version.
>> the list object didn't change, just an outside reference to its head was
>> created,
>
> The attached patch alters the example so that the list object does change (or at
> least tries to).
Does is ignore the possibility of the example in the previous version, then?
>> The opposite of "mutable" is "immutable". Are string literals immutable? They are
>> not.
>
> They might be mutable, and they might not be. The documentation deliberately
> doesn't say, because we don't want to document the details (they have changed in
> the past and are likely to change in the future).
I'm trying to point out the incompatibility with the regular meanings of
the words used.
Also see Michael's suggestion.
>> Overall the phrase "that might be shared" is a good replacement. Why not keep to
>> it?
>
> Because it's not an accurate statement of the problem. The set of objects that
> might be shared differs from the set of objects that should not change. The
> Mutability node focuses on the latter set of objects, and gives the former as an
> example but it is not the only sort of object that should not change.
But if we don't mention such cases in "Mutability", where do we cover them?
I'm also looking at the new example:
+(let* ((x (list 0.5))
+ (y (eval (list 'quote x))))
+ (setcar x 1.5) ;; The program should not do this.
+ y)
Why is this a problem? Do we expect this it could lead to a segfault?
Evaluating this expression in IELM leads to a stable result. Putting it
in a function doesn't bring any surprises either.
Example:
ELISP> (defun test (v)
(let* ((x (list v))
(y (eval (list 'quote x))))
(setcar x 1.5)
y))
test
ELISP> (test 3)
(1.5)
It's an advanced, yes, but clearly the expected behavior if someone
wrote a function like that.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-11 0:00 ` Michael Heerdegen
2020-05-11 0:26 ` Dmitry Gutov
@ 2020-05-11 1:47 ` Drew Adams
2020-05-11 1:54 ` Dmitry Gutov
2020-05-11 2:56 ` Michael Heerdegen
2020-05-11 1:53 ` Paul Eggert
2 siblings, 2 replies; 170+ messages in thread
From: Drew Adams @ 2020-05-11 1:47 UTC (permalink / raw)
To: Michael Heerdegen, Paul Eggert
Cc: ke.vigouroux, Dmitry Gutov, 40671, Richard Stallman,
Mattias Engdegård
> Symbols are constant AFAICT, their bindings
> are not (variables are not constant).
Their bindings as variables are not constant, except
for keyword symbols, nil, and t (are there any others?).
But are symbols otherwise constant, besides their
values? Depends what you mean by "symbol", perhaps.
Certainly you can change not only `symbol-value' but
also `symbol-function' and `symbol-plist'. I don't
see symbols as very constant.
[Personally, as I suggested, I don't think the text
about this gotcha should get down in the weeds about
mutable/immutable anything. I think it should stay
general, not try to catalog specific problems (e.g.
strings, conses, whatever).
It should show and explain a very simple example of
what can happen with a quoted list, and then leave
it at that. Maybe it should mention, as you said a
while back, that there are the reader, interpreter,
and byte compiler, when saying something about the
problem in general. But I already said all this,
and I said I was done here...]
BTW, in Common Lisp you can even do nasty things
like modify the `symbol-name' of a symbol. For that,
CLTL2 says:
"It is an extremely bad idea to modify a string
being used as the print name of a symbol. Such
a modification may tremendously confuse the
function `read' and the package system."
That's the _kind_ of somewhat vague gotcha
description I think we should have. Enough to
let users know they don't want to do it.
> > + A mutable object stops being mutable if it is part of an
> expression
> > +that is evaluated. For example:
>
> FWIW, I would feel better about the word "mutable" if you would
> introduce the term like "safely mutable", and then say that we call it
> just "mutable" in the following sections because this is shorter. Drew
> mentioned his dislike for the term "safe" AFAIR
I don't recall saying that, but I may have. Not
sure what's meant here. I objected to using
"dangerous", as if the gotcha was generally
hazardous to life.
> but I think "my Emacs
> won't crash if I follow this" vs. "it can crash" describes some kind of
> safety. Ignore if this comment is irrelevant because this is already
> done or treated otherwise.
To me, the problem for users is not so much that
Emacs can crash as it is that they may lose data.
Or more likely (and worth mentioning, I think, as
a motivator) that they might have a heck of a time
trying to figure out why their code doesn't seem
to behave as they expect. Seeing a quoted list
in source code can make you think new list
structure is created each time that code is run.
Code "initializing" part of some list structure
to a quoted list might give you the impression
that that's what happens each time (e.g. each
time a function that seems to do that gets called),
but the same cons from a first evaluation (or
reading) of that quoted list might remain in use
for each invocation of the function. And if you
at some point modify that cons then you might not
get your apparent "initialization" to that quoted
list each time the function's invoked.
> > + When the same value appears multiple times
^^^^^ ^^^^^^^
> > +in a program, the Lisp interpreter might save
> > +time or space by reusing existing values or
^^^^^^
> > +their components.
>
> I think we call "values" what evaluation of expressions yields, so
> values don't appear in a program (to be read). I don't know the
> backgrounds and when this can happen. Is it always the interpreter
> that does this mapping?
I think that text wasn't too bad, but I see your point.
And it's especially not good to use "value" in the two
different senses, as (1) something you see ("appears")
in a source program and (2) a runtime value that results
from reading, byte-compiling, or interpreting that source
code.
Maybe "object" or "Lisp object" instead of "value", for
#2?
(Note: I didn't read the full text. I'm just reacting
to what was cited in your mail. Sorry.)
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-11 0:00 ` Michael Heerdegen
2020-05-11 0:26 ` Dmitry Gutov
2020-05-11 1:47 ` Drew Adams
@ 2020-05-11 1:53 ` Paul Eggert
2020-05-11 3:18 ` Michael Heerdegen
2 siblings, 1 reply; 170+ messages in thread
From: Paul Eggert @ 2020-05-11 1:53 UTC (permalink / raw)
To: Michael Heerdegen
Cc: Mattias Engdegård, Dmitry Gutov, 40671, Richard Stallman,
ke.vigouroux
[-- Attachment #1: Type: text/plain, Size: 3148 bytes --]
On 5/10/20 5:00 PM, Michael Heerdegen wrote:
> Are there any classes of "types" where all members are always mutable?
Markers, for one. (This is mentioned in the previous paragraph.) There are
others. We needn't list them all here.
> Second point: you mix up objects vs. object evaluation. For conses you
> speak about the objects, for symbols about the binding (i.e. the result
> of the evaluation). Conses can also be evaluated (most programs are
> conses), but that's surely not what you want to describe. I would not
> say symbols are mutable. Symbols are constant AFAICT, their bindings
> are not (variables are not constant).
All good points. The simplest fix is to not mention symbol bindings here, as
they're a complicated topic. Their mutability issues can be documented later, if
someone wants to tackle the subject.
> FWIW, I would feel better about the word "mutable" if you would
> introduce the term like "safely mutable", and then say that we call it
> just "mutable" in the following sections because this is shorter. Drew
> mentioned his dislike for the term "safe" AFAIR but I think "my Emacs
> won't crash if I follow this" vs. "it can crash" describes some kind of
> safety. Ignore if this comment is irrelevant because this is already
> done or treated otherwise.
I think that's pretty much already done, since the definition of "mutable" says
"it is safe to change their values". I'd rather not use the term "safely
mutable" everywhere, as I don't want the manual to push the idea of "safely
mutable" as opposed to "mutable"; instead, I want the manual to look forward to
a future version where objects are either mutable or are immutable (and the
latter is checked by the interpreter).
>> + When the same value appears multiple times in a program, the Lisp
>> +interpreter might save time or space by reusing existing values or
>> +their components. For example, @code{(eq "abc" "abc")} returns
>
> I think we call "values" what evaluation of expressions yields, so
> values don't appear in a program (to be read).
They can if one feeds the values into 'eval', which runs part of a program. And
'read' can read programs. So I'm not sure I get the distinction.
> Is it always the interpreter that
> does this mapping?
This section is written at a high level and uses "interpreter" to refer to the
whole Emacs Lisp system. (This usage is longstanding in the manual.) So if any
mapping is being done, it's by the "interpreter" in that sense.
> "Same syntax" is not good as well:
I don't see that phrase used in the manual. I assume you meant "same values"?
> (eq (list 1 2 3) (list 1 2 3))
>
> doesn't provoke the pitfall you warn about, but your wording doesn't
> make clear why the one case is ok and the other is not. Maybe it's
> again as simple as saying something about objects as being part of a
> program?
I changed it to use "parts of a program" and I can changed the "values" to
"constants".
Further patch attached; it also attempts to address the issues raised by Dmitry
and Drew recently. I'm also attaching a single patch that accumulates it into
all the patches proposed for emacs-27.
[-- Attachment #2: 0001-doc-lispref-objects.texi-Mutability-More-tweaking.patch --]
[-- Type: text/x-patch, Size: 2405 bytes --]
From 3b200efd127a71c584dcb8942febc34021dffd22 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Sun, 10 May 2020 18:44:46 -0700
Subject: [PATCH] * doc/lispref/objects.texi (Mutability): More tweaking.
---
doc/lispref/objects.texi | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/doc/lispref/objects.texi b/doc/lispref/objects.texi
index 7727a630dd..136213ad66 100644
--- a/doc/lispref/objects.texi
+++ b/doc/lispref/objects.texi
@@ -2392,10 +2392,12 @@ Mutability
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, strings, and symbols. For example,
+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}.
+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 stops being mutable if it is part of an expression
that is evaluated. For example:
@@ -2413,9 +2415,7 @@ Mutability
reverse does not occur: an object that should not be changed never
becomes mutable afterwards.
- Trying to modify a constant variable signals an error
-(@pxref{Constant Variables}).
-If a program attempts to change other objects that should not be
+ 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
@@ -2424,8 +2424,8 @@ Mutability
error if a program attempts to change a constant. Ideally the Emacs
Lisp interpreter will evolve in latter direction.}
- When the same value appears multiple times in a program, the Lisp
-interpreter might save time or space by reusing existing values or
+ When similar constants occur as parts of a program, the Lisp
+interpreter might save time or space by reusing existing constants or
their components. For example, @code{(eq "abc" "abc")} returns
@code{t} if the interpreter creates only one instance of the string
literal @code{"abc"}, and returns @code{nil} if it creates two
--
2.17.1
[-- Attachment #3: 0001-Don-t-use-constant-for-values-you-shouldn-t-change.patch --]
[-- Type: text/x-patch, Size: 18478 bytes --]
From 1a41838ba32429bb44c0d3ac933d266293f6cb3c Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Sun, 10 May 2020 09:27:02 -0700
Subject: [PATCH] =?UTF-8?q?Don=E2=80=99t=20use=20=E2=80=9Cconstant?=
=?UTF-8?q?=E2=80=9D=20for=20values=20you=20shouldn=E2=80=99t=20change?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
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.
---
doc/lispintro/emacs-lisp-intro.texi | 5 +-
doc/lispref/elisp.texi | 2 +-
doc/lispref/eval.texi | 21 ++++---
doc/lispref/lists.texi | 16 ++---
doc/lispref/objects.texi | 98 +++++++++++++++--------------
doc/lispref/sequences.texi | 25 ++++----
doc/lispref/strings.texi | 11 ++--
7 files changed, 87 insertions(+), 91 deletions(-)
diff --git a/doc/lispintro/emacs-lisp-intro.texi b/doc/lispintro/emacs-lisp-intro.texi
index ea16d9ef15..46462162ca 100644
--- a/doc/lispintro/emacs-lisp-intro.texi
+++ b/doc/lispintro/emacs-lisp-intro.texi
@@ -7317,8 +7317,6 @@ setcar
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 @@ setcar
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))
diff --git a/doc/lispref/elisp.texi b/doc/lispref/elisp.texi
index bba1b63115..9a6796790c 100644
--- a/doc/lispref/elisp.texi
+++ b/doc/lispref/elisp.texi
@@ -297,7 +297,7 @@ Top
* 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
diff --git a/doc/lispref/eval.texi b/doc/lispref/eval.texi
index baddce4d9c..39f342a798 100644
--- a/doc/lispref/eval.texi
+++ b/doc/lispref/eval.texi
@@ -158,11 +158,11 @@ Self-Evaluating Forms
@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 @@ Quoting
@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 @@ Quoting
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 @@ Backquote
@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
diff --git a/doc/lispref/lists.texi b/doc/lispref/lists.texi
index fcaf4386b1..ae793d5e15 100644
--- a/doc/lispref/lists.texi
+++ b/doc/lispref/lists.texi
@@ -873,8 +873,8 @@ Modifying Lists
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 @@ Setcar
@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 @@ Setcar
@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 @@ Setcdr
@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 @@ Rearrangement
@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
diff --git a/doc/lispref/objects.texi b/doc/lispref/objects.texi
index 1d5b2c690f..136213ad66 100644
--- a/doc/lispref/objects.texi
+++ b/doc/lispref/objects.texi
@@ -46,10 +46,6 @@ Lisp Data Types
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 @@ 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.
@end menu
@node Printed Representation
@@ -2379,51 +2375,59 @@ Equality Predicates
@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.
-
- 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.
-
- 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}.
-
- 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.
-
- 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.
-
- When the same constant occurs multiple times in a program, the Lisp
+ 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 @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 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 stops being mutable if it is part of an expression
+that is evaluated. For example:
+
+@example
+(let* ((x (list 0.5))
+ (y (eval (list 'quote x))))
+ (setcar x 1.5) ;; The program should not do this.
+ y)
+@end example
+
+@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.
diff --git a/doc/lispref/sequences.texi b/doc/lispref/sequences.texi
index 1cb0d05cc7..91c3049f87 100644
--- a/doc/lispref/sequences.texi
+++ b/doc/lispref/sequences.texi
@@ -183,11 +183,11 @@ Sequence Functions
@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 @@ Sequence Functions
@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 @@ Sequence Functions
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 @@ Sequence Functions
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 @@ Sequence Functions
@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 @@ Array Functions
@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 @@ Array Functions
@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 @@ Array Functions
@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 @@ Array Functions
@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 @@ Array Functions
@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 @@ Vectors
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:
diff --git a/doc/lispref/strings.texi b/doc/lispref/strings.texi
index a4c9c2549c..70c3b3cf4b 100644
--- a/doc/lispref/strings.texi
+++ b/doc/lispref/strings.texi
@@ -49,10 +49,9 @@ String Basics
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 @@ 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.
-@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}
--
2.17.1
^ permalink raw reply related [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-11 1:47 ` Drew Adams
@ 2020-05-11 1:54 ` Dmitry Gutov
2020-05-11 2:33 ` Drew Adams
2020-05-11 2:56 ` Michael Heerdegen
1 sibling, 1 reply; 170+ messages in thread
From: Dmitry Gutov @ 2020-05-11 1:54 UTC (permalink / raw)
To: Drew Adams, Michael Heerdegen, Paul Eggert
Cc: ke.vigouroux, 40671, Richard Stallman, Mattias Engdegård
On 11.05.2020 04:47, Drew Adams wrote:
>> Drew
>> mentioned his dislike for the term "safe" AFAIR
> I don't recall saying that, but I may have. Not
> sure what's meant here. I objected to using
> "dangerous", as if the gotcha was generally
> hazardous to life.
Would "unsafe mutations" be better?
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-11 0:44 ` Dmitry Gutov
@ 2020-05-11 1:57 ` Paul Eggert
2020-05-12 1:59 ` Dmitry Gutov
0 siblings, 1 reply; 170+ messages in thread
From: Paul Eggert @ 2020-05-11 1:57 UTC (permalink / raw)
To: Dmitry Gutov
Cc: ke.vigouroux, 40671, Michael Heerdegen, Mattias Engdegård,
Richard Stallman
On 5/10/20 5:44 PM, Dmitry Gutov wrote:
> "Indeed"?
Indeed yes. :-)
> The changing "mutability" status is imaginary, however.
It's part of a spec. Not every constraint in a spec needs to be enforced
directly by the implementation. That doesn't mean these constraints are "imaginary".
> This also requires the reader to read the manual without missing a reference. A
> regular person would not understand your meaning of "mutable" without following
> the reference to {Mutability}.
If a paragraph says "mutable" and has a cross-reference to the "Mutability"
section, that's good enough. This is a reference manual, not a tutorial, and we
can assume a reasonable level of competence on the part of the reader.
> Does is ignore the possibility of the example in the previous version, then?
I don't understand this remark.
> I'm trying to point out the incompatibility with the regular meanings of the
> words used.
>> Because it's not an accurate statement of the problem. The set of objects that
>> might be shared differs from the set of objects that should not change. The
>> Mutability node focuses on the latter set of objects, and gives the former as an
>> example but it is not the only sort of object that should not change.
>
> But if we don't mention such cases in "Mutability", where do we cover them?
Fair enough. I added an example of such a case to "Mutability" in the proposal
in my most-recent email (Bug#40671#441).
> +(let* ((x (list 0.5))
> + (y (eval (list 'quote x))))
> + (setcar x 1.5) ;; The program should not do this.
> + y)
>
> Why is this a problem? Do we expect this it could lead to a segfault?
Probably not a segfault in the current implementation, but the behavior isn't
defined. And we don't want the behavior to be defined, as that would prohibit
some optimizations that may be coming down the road.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-11 1:54 ` Dmitry Gutov
@ 2020-05-11 2:33 ` Drew Adams
0 siblings, 0 replies; 170+ messages in thread
From: Drew Adams @ 2020-05-11 2:33 UTC (permalink / raw)
To: Dmitry Gutov, Michael Heerdegen, Paul Eggert
Cc: ke.vigouroux, 40671, Richard Stallman, Mattias Engdegård
> >> Drew mentioned his dislike for the term "safe" AFAIR
> >
> > I don't recall saying that, but I may have. Not
> > sure what's meant here. I objected to using
> > "dangerous", as if the gotcha was generally
> > hazardous to life.
>
> Would "unsafe mutations" be better?
I didn't really want to get into this with you
guys. I just wanted to reply to Michael's
message. But...
I'd prefer that we speak of "modification",
not "mutation". "Mutation" has a connotation
of something happening on its own. If that
were the case then we wouldn't be trying to
tell people not to do something!
I'm not a big fan of "safe" (or, especially,
"dangerous"), unless it's about human safety
(e.g. an airline maintenance manual).
I'd prefer that we just tell users that if
they do certain things then the behavior of
their code _might not be what they expect_.
Or that the behavior is "undefined". And
let it go at that.
What's important is to give them some idea
of _what_ it is that we're telling them not
to do. I don't have an example, but I think
a simple quoted-list example can get the point
across. And then you can say something about
strings or whatever, if you like, without
bothering with more examples.
My advice: don't try to explain too well
just what happens. See if you can get the
general point across without any exhaustive
rundown of a bunch of different cases or
trying to be too exact.
If a user understands that internal Lisp
structures (objects) can get created by
(1) the Lisp reader, (2) the interpreter, and
(3) the byte compiler, and if s?he understands
that what's seen in the source code does not
necessarily correspond to when a corresponding
Lisp object gets created, then s?he'll get it.
Just when, and how many times does the source
code of a quoted list result in a new cons?
You can't really know. When it's read?
byte-compiled?
A new Lisp user thinks in terms of interpreted
source code. Seeing a quoted list, s?he thinks
that a new cons is created each time it's read,
interpreted, or byte-compiled. But that may
not (typically does not) happen. If you modify
the cons that resulted from a source-code quoted
list then that _same_ cons might be baked into
the internal code thereafter.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-11 1:47 ` Drew Adams
2020-05-11 1:54 ` Dmitry Gutov
@ 2020-05-11 2:56 ` Michael Heerdegen
2020-05-11 4:21 ` Drew Adams
1 sibling, 1 reply; 170+ messages in thread
From: Michael Heerdegen @ 2020-05-11 2:56 UTC (permalink / raw)
To: Drew Adams
Cc: ke.vigouroux, Paul Eggert, 40671, Mattias Engdegård,
Dmitry Gutov, Richard Stallman
Drew Adams <drew.adams@oracle.com> writes:
> But are symbols otherwise constant, besides their
> values? Depends what you mean by "symbol", perhaps.
> Certainly you can change not only `symbol-value' but
> also `symbol-function' and `symbol-plist'. I don't
> see symbols as very constant.
Also makes sense, yes.
> I think that text wasn't too bad, but I see your point.
>
> And it's especially not good to use "value" in the two
> different senses, as (1) something you see ("appears")
> in a source program and (2) a runtime value that results
> from reading, byte-compiling, or interpreting that source
> code.
>
> Maybe "object" or "Lisp object" instead of "value", for
> #2?
The term "value" is used all over the place in the manual for #2, so
people are familiar with it, we need a better term for (1) instead I
think. (info "(elisp) Equality Predicates") already uses the term
"literal object" btw:
The Emacs Lisp byte compiler may collapse identical literal
objects, such as literal strings, into references to the same
object, with the effect that the byte-compiled code will compare
such objects as ‘eq’, while the interpreted version of the same
code will not.
Michael.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-11 1:53 ` Paul Eggert
@ 2020-05-11 3:18 ` Michael Heerdegen
0 siblings, 0 replies; 170+ messages in thread
From: Michael Heerdegen @ 2020-05-11 3:18 UTC (permalink / raw)
To: Paul Eggert
Cc: Mattias Engdegård, Dmitry Gutov, 40671, Richard Stallman,
ke.vigouroux
Paul Eggert <eggert@cs.ucla.edu> writes:
> All good points. The simplest fix is to not mention symbol bindings
> here, as they're a complicated topic.
Yes, agreed.
> >> + When the same value appears multiple times in a program, the Lisp
> >> +interpreter might save time or space by reusing existing values or
> >> +their components. For example, @code{(eq "abc" "abc")} returns
> >
> > I think we call "values" what evaluation of expressions yields, so
> > values don't appear in a program (to be read).
>
> They can if one feeds the values into 'eval', which runs part of a
> program. And 'read' can read programs. So I'm not sure I get the
> distinction.
Now I get how you meant this. I read the sentence more with a written
program and syntax in mind.
Michael.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-11 2:56 ` Michael Heerdegen
@ 2020-05-11 4:21 ` Drew Adams
2020-05-11 4:51 ` Michael Heerdegen
0 siblings, 1 reply; 170+ messages in thread
From: Drew Adams @ 2020-05-11 4:21 UTC (permalink / raw)
To: Michael Heerdegen
Cc: ke.vigouroux, Paul Eggert, 40671, Mattias Engdegård,
Dmitry Gutov, Richard Stallman
(This ended up long and a bit off-topic; sorry.
Hope it still helps.)
> > And it's especially not good to use "value" in the two
> > different senses, as (1) something you see ("appears")
> > in a source program and (2) a runtime value that results
> > from reading, byte-compiling, or interpreting that source
> > code.
> >
> > Maybe "object" or "Lisp object" instead of "value", for
> > #2?
>
> The term "value" is used all over the place in the manual for #2, so
> people are familiar with it, we need a better term for (1) instead I
> think. (info "(elisp) Equality Predicates") already uses the term
> "literal object" btw:
>
> The Emacs Lisp byte compiler may collapse identical literal
> objects, such as literal strings, into references to the same
> object, with the effect that the byte-compiled code will compare
> such objects as ‘eq’, while the interpreted version of the same
> code will not.
BTW, that node does NOT already contain that text.
That paragraph is new for Emacs 27, which is not yet
released. IOW, that text is _proposed_ for Emacs 27.
But OK. That describes the problem as being about
"literal objects".
That's essentially the message we're discussing, I
think, but it should be broadened beyond just the
byte-compiler, I think.
Where, if anywhere, does the manual define or describe
"literal objects"? I don't think we want to be doing
that, unless it's done carefully.
For the message we're talking about, I'd say start by
talking about source code: forms, sexps.
Yes, the sexps that are problematic are, I suppose,
what that text calls "literal objects". But I don't
see that term defined anywhere. And it seems odd to
me to talk about source-code thingies as "objects".
Maybe the result of reading, or the result of some
initial stage of byte-compiling or interpreting, is a
"literal object", but is a source-code sexp a "literal
object"?
A "literal string" makes sense to me, as a string
in source code ("..."). But "literal object" doesn't
sound like a source-code thing. Perhaps that's what
literal numbers, strings, etc. in source code are
called now - "objects"? Sounds odd to me.
Checking `i literal' in the Emacs 27 manual, I see
no "literal object", but I do see "literal evaluation"
and "literal in rx", where "literal" is used as a noun
(in both cases presumably).
However, the former index entry takes you to node
`Self-Evaluating Forms', which never once uses the
word "literal" (as adjective or noun) - it talks only
about "forms", i.e., source code. That text looks OK.
The index item seems wrong - you never get any text
that tells you anything about "literal evaluation".
This node, and index entry "literal evaluation" are
in Emacs 26 (and probably earlier).
[Index entry "literal in rx" takes you to node `Rx
Constructs', where you find `(literal EXPR)', which
is about matching a "literal string". To me, "literal
string" is clear enough, and I think of it as both a
source-code thing (text) and as a Lisp object (after
reading the text, for example). This node is new for
Emacs 27.]
Searching the Emacs 27 Elisp manual for "literal"
I see that there is another occurrence of "literal
object", also in a node that is new for release 27,
`pcase Macro'.
There too the term "literal object"is totally
unexplained: "Matches if EXPL equals the literal
object. This is a special case of ‘'VAL’, above,
possible because literal objects of these types
are self-quoting."
(The "possible because..." is not correct English,
and I don't know what it's trying to say. Maybe
"possibly because..." was meant. Or maybe what
was meant was to end a sentence after "above" and
start a new sentence with "This is possible
because...".)
And again, in another new-to-Emacs-27 node,
`Backquote Patterns', I see "literal object":
"Matches if the corresponding element of EXPVAL
is ‘equal’ to the specified literal object." And
again, the term is totally unexplained.
(That node also has "literal symbol", which, like
"literal string" doesn't shock me. It is "literal
object" that I find odd.)
Both Emacs 27 and 26, node `Mode-Specific Indent',
mention "a literal value (usually zero)". That's
OK, I guess, but I think it's untrue. I think
what's meant is just "a number (usually zero)".
There's nothing literal about it.
Node `Rx Constructs' of Emacs 27 introduces
"Literals" (noun) as forms (source-code sexps),
and shows that they can be strings or chars.
I don't have a problem with that.
Node `Rx Functions' says "if `literal' or `regexp'
forms are used", and I guess that's referring to
the forms `(literal...)' and `(regexp...)'
introduced in node `Rx Constructs'. And it refers
to "string literals". All of that's OK.
Node `Extending Rx' mentions "a list literal".
Again, like string literal, char literal, etc.,
this isn't introduced anywhere that I can see,
but that's OK - use of "literal" as a noun in
such cases clearly means the same as "literal
string" etc.
Node `Module Initialization' is another new one
for Emacs 27, and another place where "literal"
is used as a noun: "number literal". Again, no
problem for me with that (like "string literal").
All other occurrences of "literal" in the manual
are about literal chars, finding a file literally,
displaying or matching text literally, or
replacing literal text. No problem there, and
nothing new there.
In sum, "literal object" is nowhere defined,
described, or explained. And "object" sounds
wrong, to me, when referring to source-code text.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-11 4:21 ` Drew Adams
@ 2020-05-11 4:51 ` Michael Heerdegen
2020-05-11 6:28 ` Paul Eggert
0 siblings, 1 reply; 170+ messages in thread
From: Michael Heerdegen @ 2020-05-11 4:51 UTC (permalink / raw)
To: Drew Adams
Cc: ke.vigouroux, Paul Eggert, 40671, Mattias Engdegård,
Dmitry Gutov, Richard Stallman
Drew Adams <drew.adams@oracle.com> writes:
> In sum, "literal object" is nowhere defined,
> described, or explained. And "object" sounds
> wrong, to me, when referring to source-code text.
Yes, it's vague. Maybe the place I cited should formulated otherwise,
since we didn't use the term for the "no no" objects, for reasons.
BTW (also @Paul) there are some places (five or so) in Elisp source
files that look like
(nconc '(x y z) (get-some-list))
Should they be rewritten?
Michael.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-11 4:51 ` Michael Heerdegen
@ 2020-05-11 6:28 ` Paul Eggert
2020-05-11 13:57 ` Noam Postavsky
` (3 more replies)
0 siblings, 4 replies; 170+ messages in thread
From: Paul Eggert @ 2020-05-11 6:28 UTC (permalink / raw)
To: Michael Heerdegen, Drew Adams
Cc: ke.vigouroux, Dmitry Gutov, 40671, Richard Stallman,
Mattias Engdegård
[-- Attachment #1: Type: text/plain, Size: 288 bytes --]
On 5/10/20 9:51 PM, Michael Heerdegen wrote:
> BTW (also @Paul) there are some places (five or so) in Elisp source
> files that look like
>
> (nconc '(x y z) (get-some-list))
>
> Should they be rewritten?
Yes, of course. Does the attached diff (against master) match what you found?
[-- Attachment #2: nconc.diff --]
[-- Type: text/x-patch, Size: 6959 bytes --]
diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
index 4f72251aed..fd6c6fe1ad 100644
--- a/lisp/emacs-lisp/byte-opt.el
+++ b/lisp/emacs-lisp/byte-opt.el
@@ -1509,14 +1509,13 @@ byte-compile-side-effect-and-error-free-ops
byte-current-buffer byte-stack-ref))
(defconst byte-compile-side-effect-free-ops
- (nconc
- '(byte-varref byte-nth byte-memq byte-car byte-cdr byte-length byte-aref
- byte-symbol-value byte-get byte-concat2 byte-concat3 byte-sub1 byte-add1
- byte-eqlsign byte-gtr byte-lss byte-leq byte-geq byte-diff byte-negate
- byte-plus byte-max byte-min byte-mult byte-char-after byte-char-syntax
- byte-buffer-substring byte-string= byte-string< byte-nthcdr byte-elt
- byte-member byte-assq byte-quo byte-rem byte-substring)
- byte-compile-side-effect-and-error-free-ops))
+ `(byte-varref byte-nth byte-memq byte-car byte-cdr byte-length byte-aref
+ byte-symbol-value byte-get byte-concat2 byte-concat3 byte-sub1 byte-add1
+ byte-eqlsign byte-gtr byte-lss byte-leq byte-geq byte-diff byte-negate
+ byte-plus byte-max byte-min byte-mult byte-char-after byte-char-syntax
+ byte-buffer-substring byte-string= byte-string< byte-nthcdr byte-elt
+ byte-member byte-assq byte-quo byte-rem byte-substring
+ ,@byte-compile-side-effect-and-error-free-ops))
;; This crock is because of the way DEFVAR_BOOL variables work.
;; Consider the code
diff --git a/lisp/frameset.el b/lisp/frameset.el
index 10c6914f52..5850561928 100644
--- a/lisp/frameset.el
+++ b/lisp/frameset.el
@@ -396,17 +396,17 @@ frameset-prop
;; or, if you're only changing a few items,
;;
;; (defvar my-filter-alist
-;; (nconc '((my-param1 . :never)
-;; (my-param2 . my-filtering-function))
-;; frameset-filter-alist)
+;; `((my-param1 . :never)
+;; (my-param2 . my-filtering-function)
+;; ,@frameset-filter-alist)
;; "My brief customized parameter filter alist.")
;;
;; and pass it to the FILTER arg of the save/restore functions,
;; ALWAYS taking care of not modifying the original lists; if you're
;; going to do any modifying of my-filter-alist, please use
;;
-;; (nconc '((my-param1 . :never) ...)
-;; (copy-sequence frameset-filter-alist))
+;; `(((my-param1 . :never) ...)
+;; ,@(copy-sequence frameset-filter-alist))
;;
;; One thing you shouldn't forget is that they are alists, so searching
;; in them is sequential. If you just want to change the default of
@@ -445,39 +445,38 @@ frameset-session-filter-alist
;;;###autoload
(defvar frameset-persistent-filter-alist
- (nconc
- '((background-color . frameset-filter-sanitize-color)
- (buffer-list . :never)
- (buffer-predicate . :never)
- (buried-buffer-list . :never)
- ;; Don't save the 'client' parameter to avoid that a subsequent
- ;; `save-buffers-kill-terminal' in a non-client session barks at
- ;; the user (Bug#29067).
- (client . :never)
- (delete-before . :never)
- (font . frameset-filter-font-param)
- ;; Don't save font-backend because we cannot guarantee the new
- ;; session will support the saved backend anyway. (Bug#38442)
- (font-backend . :never)
- (foreground-color . frameset-filter-sanitize-color)
- (frameset--text-pixel-height . :save)
- (frameset--text-pixel-width . :save)
- (fullscreen . frameset-filter-shelve-param)
- (GUI:font . frameset-filter-unshelve-param)
- (GUI:fullscreen . frameset-filter-unshelve-param)
- (GUI:height . frameset-filter-unshelve-param)
- (GUI:width . frameset-filter-unshelve-param)
- (height . frameset-filter-shelve-param)
- (outer-window-id . :never)
- (parent-frame . :never)
- (parent-id . :never)
- (mouse-wheel-frame . :never)
- (tty . frameset-filter-tty-to-GUI)
- (tty-type . frameset-filter-tty-to-GUI)
- (width . frameset-filter-shelve-param)
- (window-id . :never)
- (window-system . :never))
- frameset-session-filter-alist)
+ `((background-color . frameset-filter-sanitize-color)
+ (buffer-list . :never)
+ (buffer-predicate . :never)
+ (buried-buffer-list . :never)
+ ;; Don't save the 'client' parameter to avoid that a subsequent
+ ;; `save-buffers-kill-terminal' in a non-client session barks at
+ ;; the user (Bug#29067).
+ (client . :never)
+ (delete-before . :never)
+ (font . frameset-filter-font-param)
+ ;; Don't save font-backend because we cannot guarantee the new
+ ;; session will support the saved backend anyway. (Bug#38442)
+ (font-backend . :never)
+ (foreground-color . frameset-filter-sanitize-color)
+ (frameset--text-pixel-height . :save)
+ (frameset--text-pixel-width . :save)
+ (fullscreen . frameset-filter-shelve-param)
+ (GUI:font . frameset-filter-unshelve-param)
+ (GUI:fullscreen . frameset-filter-unshelve-param)
+ (GUI:height . frameset-filter-unshelve-param)
+ (GUI:width . frameset-filter-unshelve-param)
+ (height . frameset-filter-shelve-param)
+ (outer-window-id . :never)
+ (parent-frame . :never)
+ (parent-id . :never)
+ (mouse-wheel-frame . :never)
+ (tty . frameset-filter-tty-to-GUI)
+ (tty-type . frameset-filter-tty-to-GUI)
+ (width . frameset-filter-shelve-param)
+ (window-id . :never)
+ (window-system . :never)
+ ,@frameset-session-filter-alist)
"Parameters to filter for persistent framesets.
DO NOT MODIFY. See `frameset-filter-alist' for a full description.")
diff --git a/lisp/gnus/gnus-sum.el b/lisp/gnus/gnus-sum.el
index 6f367692dd..595df607f5 100644
--- a/lisp/gnus/gnus-sum.el
+++ b/lisp/gnus/gnus-sum.el
@@ -1501,9 +1501,9 @@ gnus-summary-mode-line-format-alist
;; This is here rather than in gnus-art for compilation reasons.
(defvar gnus-article-mode-line-format-alist
- (nconc '((?w (gnus-article-wash-status) ?s)
- (?m (gnus-article-mime-part-status) ?s))
- gnus-summary-mode-line-format-alist))
+ (nconc `((?w (gnus-article-wash-status) ?s)
+ (?m (gnus-article-mime-part-status) ?s)
+ ,@gnus-summary-mode-line-format-alist)))
(defvar gnus-last-search-regexp nil
"Default regexp for article search command.")
^ permalink raw reply related [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-11 6:28 ` Paul Eggert
@ 2020-05-11 13:57 ` Noam Postavsky
2020-05-11 22:36 ` Michael Heerdegen
2020-05-11 22:30 ` Michael Heerdegen
` (2 subsequent siblings)
3 siblings, 1 reply; 170+ messages in thread
From: Noam Postavsky @ 2020-05-11 13:57 UTC (permalink / raw)
To: Paul Eggert
Cc: ke.vigouroux, Richard Stallman, Michael Heerdegen,
Mattias Engdegård, Dmitry Gutov, 40671
Paul Eggert <eggert@cs.ucla.edu> writes:
> (defvar gnus-article-mode-line-format-alist
> - (nconc '((?w (gnus-article-wash-status) ?s)
> - (?m (gnus-article-mime-part-status) ?s))
> - gnus-summary-mode-line-format-alist))
> + (nconc `((?w (gnus-article-wash-status) ?s)
> + (?m (gnus-article-mime-part-status) ?s)
> + ,@gnus-summary-mode-line-format-alist)))
You meant to remove the nconc call too, right?
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-11 6:28 ` Paul Eggert
2020-05-11 13:57 ` Noam Postavsky
@ 2020-05-11 22:30 ` Michael Heerdegen
2020-05-12 3:20 ` Richard Stallman
[not found] ` <05BEF593-F16A-4DEE-98BC-653221F1F9EE@acm.org>
3 siblings, 0 replies; 170+ messages in thread
From: Michael Heerdegen @ 2020-05-11 22:30 UTC (permalink / raw)
To: Paul Eggert
Cc: ke.vigouroux, 40671, Mattias Engdegård, Dmitry Gutov,
Richard Stallman
Paul Eggert <eggert@cs.ucla.edu> writes:
> Yes, of course. Does the attached diff (against master) match what you
> found?
Yes, I think so.
Thanks,
Michael.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-11 13:57 ` Noam Postavsky
@ 2020-05-11 22:36 ` Michael Heerdegen
0 siblings, 0 replies; 170+ messages in thread
From: Michael Heerdegen @ 2020-05-11 22:36 UTC (permalink / raw)
To: Noam Postavsky
Cc: ke.vigouroux, Paul Eggert, 40671, Mattias Engdegård,
Dmitry Gutov, Richard Stallman
Noam Postavsky <npostavs@gmail.com> writes:
> Paul Eggert <eggert@cs.ucla.edu> writes:
>
> > (defvar gnus-article-mode-line-format-alist
> > - (nconc '((?w (gnus-article-wash-status) ?s)
> > - (?m (gnus-article-mime-part-status) ?s))
> > - gnus-summary-mode-line-format-alist))
> > + (nconc `((?w (gnus-article-wash-status) ?s)
> > + (?m (gnus-article-mime-part-status) ?s)
> > + ,@gnus-summary-mode-line-format-alist)))
>
> You meant to remove the nconc call too, right?
That, and, the code still makes literal lists to alist entries. If you
modify these associations, you modify these literal lists.
I wonder how many of such uses of backquote expressions used to
construct alists are scattered throughout the Emacs code.
Michael.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-11 1:57 ` Paul Eggert
@ 2020-05-12 1:59 ` Dmitry Gutov
2020-05-17 1:28 ` Paul Eggert
0 siblings, 1 reply; 170+ messages in thread
From: Dmitry Gutov @ 2020-05-12 1:59 UTC (permalink / raw)
To: Paul Eggert
Cc: Michael Heerdegen, ke.vigouroux, 40671, Mattias Engdegård,
Richard Stallman
On 11.05.2020 04:57, Paul Eggert wrote:
> On 5/10/20 5:44 PM, Dmitry Gutov wrote:
>
>> "Indeed"?
>
> Indeed yes. :-)
That paragraph doesn't scan. You could replace that word with "And", though.
>> The changing "mutability" status is imaginary, however.
>
> It's part of a spec. Not every constraint in a spec needs to be enforced
> directly by the implementation. That doesn't mean these constraints are "imaginary".
Part of the "spec" you just added in this series of patches.
I think that's exactly what a "constraint" means: something that is
enforced.
>>> Because it's not an accurate statement of the problem. The set of objects that
>>> might be shared differs from the set of objects that should not change. The
>>> Mutability node focuses on the latter set of objects, and gives the former as an
>>> example but it is not the only sort of object that should not change.
>>
>> But if we don't mention such cases in "Mutability", where do we cover them?
>
> Fair enough. I added an example of such a case to "Mutability" in the proposal
> in my most-recent email (Bug#40671#441).
Curious case of an meaningful reference where I have to construct the
URL manually anyway. The symbol-name example? I'm not sure it's really
important to warn about this one in particular.
But are we effectively saying "there exist values that are unsafe to
modify, for example, any return values of symbol-name", and that's it?
When one tries to describe "unsafe" things to do, they don't just give a
few examples, they usually try to cover all cases. Perhaps by including
some false positives (which the 'let*' example below, I think, is), but
trying hard to avoid false negatives.
Inventing a name for such values doesn't help if the user doesn't have
enough knowledge to avoid all members of this set. Or is "part of an
expression that is evaluated" after all the test we'll be teaching?
By the way, I have read last two paragraphs of that section now. C and
"constants" are still there.
>> +(let* ((x (list 0.5))
>> + (y (eval (list 'quote x))))
>> + (setcar x 1.5) ;; The program should not do this.
>> + y)
>>
>> Why is this a problem? Do we expect this it could lead to a segfault?
>
> Probably not a segfault in the current implementation, but the behavior isn't
> defined. And we don't want the behavior to be defined, as that would prohibit
> some optimizations that may be coming down the road.
I'm curious to see the discussion about actually making this error at
runtime in one of the next Emacs version.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-11 6:28 ` Paul Eggert
2020-05-11 13:57 ` Noam Postavsky
2020-05-11 22:30 ` Michael Heerdegen
@ 2020-05-12 3:20 ` Richard Stallman
2020-05-12 4:24 ` Michael Heerdegen
[not found] ` <05BEF593-F16A-4DEE-98BC-653221F1F9EE@acm.org>
3 siblings, 1 reply; 170+ messages in thread
From: Richard Stallman @ 2020-05-12 3:20 UTC (permalink / raw)
To: Paul Eggert; +Cc: ke.vigouroux, 40671, michael_heerdegen, mattiase, dgutov
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
Would someone like to search all our Lisp sources for "(nconc '" and
check every occurrence?
--
Dr Richard Stallman
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-12 3:20 ` Richard Stallman
@ 2020-05-12 4:24 ` Michael Heerdegen
2020-05-13 3:57 ` Richard Stallman
0 siblings, 1 reply; 170+ messages in thread
From: Michael Heerdegen @ 2020-05-12 4:24 UTC (permalink / raw)
To: Richard Stallman; +Cc: ke.vigouroux, Paul Eggert, 40671, mattiase, dgutov
Richard Stallman <rms@gnu.org> writes:
> Would someone like to search all our Lisp sources for "(nconc '" and
> check every occurrence?
Paul and I found the same matches with probably different methods - so I
think this already has been done.
Michael.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-12 4:24 ` Michael Heerdegen
@ 2020-05-13 3:57 ` Richard Stallman
2020-05-13 5:05 ` Michael Heerdegen
0 siblings, 1 reply; 170+ messages in thread
From: Richard Stallman @ 2020-05-13 3:57 UTC (permalink / raw)
To: Michael Heerdegen; +Cc: mattiase, ke.vigouroux, eggert, 40671, dgutov
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> Paul and I found the same matches with probably different methods - so I
> think this already has been done.
When you found them, did you fix them?
--
Dr Richard Stallman
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-13 3:57 ` Richard Stallman
@ 2020-05-13 5:05 ` Michael Heerdegen
2020-05-14 5:14 ` Richard Stallman
0 siblings, 1 reply; 170+ messages in thread
From: Michael Heerdegen @ 2020-05-13 5:05 UTC (permalink / raw)
To: Richard Stallman; +Cc: mattiase, ke.vigouroux, eggert, 40671, dgutov
Richard Stallman <rms@gnu.org> writes:
> When you found them, did you fix them?
Paul has already proposed a patch, I guess he will install it later
(maybe after caring about the remarks by Noam and me).
Michael.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-13 5:05 ` Michael Heerdegen
@ 2020-05-14 5:14 ` Richard Stallman
0 siblings, 0 replies; 170+ messages in thread
From: Richard Stallman @ 2020-05-14 5:14 UTC (permalink / raw)
To: Michael Heerdegen; +Cc: ke.vigouroux, mattiase, eggert, 40671, dgutov
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> Paul has already proposed a patch, I guess he will install it later
> (maybe after caring about the remarks by Noam and me).
Thank you, and Paul.
--
Dr Richard Stallman
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
[not found] ` <05BEF593-F16A-4DEE-98BC-653221F1F9EE@acm.org>
@ 2020-05-17 0:11 ` Paul Eggert
2020-05-17 9:43 ` Mattias Engdegård
0 siblings, 1 reply; 170+ messages in thread
From: Paul Eggert @ 2020-05-17 0:11 UTC (permalink / raw)
To: Mattias Engdegård; +Cc: Michael Heerdegen, 40671
[-- Attachment #1: Type: text/plain, Size: 670 bytes --]
On 5/11/20 2:29 AM, Mattias Engdegård wrote:
> As an experiment, I added an immutable cons type some time ago and found these and more. The attachment contains some of the adjustments made at the time. This isn't complete; I never got to a full bootstrap, for unrelated reasons.
Thanks for sending that patch. Even if incomplete, it's better to not try to
modify constants so I installed the attached into master; it's derived from your
patch and supersedes my earlier (typo-containing) patch about nconc.
> By the way: Is there any reason you prefer `(a b c ,@tail) to (append '(a b c) tail)?
No, I just wasn't thinking. The attached patch uses 'append'.
[-- Attachment #2: 0001-Don-t-attempt-to-modify-constant-conses.txt --]
[-- Type: text/plain, Size: 14483 bytes --]
From aed11100f8056804d2e438fc4e793dc099d0e06f Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Sat, 16 May 2020 17:04:15 -0700
Subject: [PATCH] =?UTF-8?q?Don=E2=80=99t=20attempt=20to=20modify=20constan?=
=?UTF-8?q?t=20conses?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
From a patch privately suggested by Mattias Engdegård on 2020-05-11
in a followup to Bug#40671.
* admin/charsets/cp51932.awk:
* admin/charsets/eucjp-ms.awk:
Generate code that does not modify constant conses.
* doc/misc/emacs-mime.texi (Encoding Customization):
* lisp/emacs-lisp/byte-opt.el (byte-compile-side-effect-free-ops):
* lisp/frameset.el (frameset-persistent-filter-alist):
* lisp/gnus/gnus-sum.el (gnus-article-mode-line-format-alist):
Use append instead of nconc.
* lisp/language/japanese.el (japanese-ucs-cp932-to-jis-map)
(jisx0213-to-unicode):
Use mapcar instead of mapc.
* lisp/language/lao-util.el (lao-transcription-consonant-alist)
(lao-transcription-vowel-alist):
* lisp/language/tibetan.el (tibetan-subjoined-transcription-alist):
Use copy-sequence.
* test/src/fns-tests.el (fns-tests-nreverse):
(fns-tests-sort, fns-tests-collate-sort)
(fns-tests-string-version-lessp, fns-tests-mapcan):
Use copy-sequence, vector, and list.
---
admin/charsets/cp51932.awk | 13 +++++++------
admin/charsets/eucjp-ms.awk | 14 ++++++++------
doc/misc/emacs-mime.texi | 2 +-
lisp/emacs-lisp/byte-opt.el | 2 +-
lisp/frameset.el | 12 ++++++------
lisp/gnus/gnus-sum.el | 6 +++---
lisp/language/japanese.el | 10 +++++-----
lisp/language/lao-util.el | 16 ++++++++++------
lisp/language/tibetan.el | 8 +++++---
test/src/fns-tests.el | 34 +++++++++++++++++-----------------
10 files changed, 63 insertions(+), 54 deletions(-)
diff --git a/admin/charsets/cp51932.awk b/admin/charsets/cp51932.awk
index 6aac98815b..c355509524 100644
--- a/admin/charsets/cp51932.awk
+++ b/admin/charsets/cp51932.awk
@@ -43,13 +43,14 @@ BEGIN {
END {
print ")))";
- print " (mapc #'(lambda (x)";
- print " (setcar x (decode-char 'japanese-jisx0208 (car x))))";
- print " map)";
+ print " (setq map (mapcar (lambda (x)";
+ print " (cons (decode-char 'japanese-jisx0208 (car x))";
+ print " (cdr x)))";
+ print " map))";
print " (define-translation-table 'cp51932-decode map)";
- print " (mapc #'(lambda (x)";
- print " (let ((tmp (car x)))";
- print " (setcar x (cdr x)) (setcdr x tmp)))";
+ print " (mapc (lambda (x)";
+ print " (let ((tmp (car x)))";
+ print " (setcar x (cdr x)) (setcdr x tmp)))";
print " map)";
print " (define-translation-table 'cp51932-encode map))";
print "";
diff --git a/admin/charsets/eucjp-ms.awk b/admin/charsets/eucjp-ms.awk
index 0c9f94d0f4..f6a6748ce5 100644
--- a/admin/charsets/eucjp-ms.awk
+++ b/admin/charsets/eucjp-ms.awk
@@ -93,15 +93,17 @@ function write_entry (unicode) {
END {
print ")))";
- print " (mapc #'(lambda (x)";
+ print " (setq map";
+ print " (mapcar";
+ print " (lambda (x)";
print " (let ((code (logand (car x) #x7F7F)))";
print " (if (integerp (cdr x))";
- print " (setcar x (decode-char 'japanese-jisx0208 code))";
- print " (setcar x (decode-char 'japanese-jisx0212 code))";
- print " (setcdr x (cadr x)))))";
- print " map)";
+ print " (cons (decode-char 'japanese-jisx0208 code) (cdr x))";
+ print " (cons (decode-char 'japanese-jisx0212 code)"
+ print " (cadr x)))))";
+ print " map))";
print " (define-translation-table 'eucjp-ms-decode map)";
- print " (mapc #'(lambda (x)";
+ print " (mapc (lambda (x)";
print " (let ((tmp (car x)))";
print " (setcar x (cdr x)) (setcdr x tmp)))";
print " map)";
diff --git a/doc/misc/emacs-mime.texi b/doc/misc/emacs-mime.texi
index 42a7750b9a..2f38dcd495 100644
--- a/doc/misc/emacs-mime.texi
+++ b/doc/misc/emacs-mime.texi
@@ -917,7 +917,7 @@ Encoding Customization
@lisp
(add-to-list 'gnus-newsgroup-variables 'mm-coding-system-priorities)
(setq gnus-parameters
- (nconc
+ (append
;; Some charsets are just examples!
'(("^cn\\." ;; Chinese
(mm-coding-system-priorities
diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
index 4f72251aed..62b82e4f32 100644
--- a/lisp/emacs-lisp/byte-opt.el
+++ b/lisp/emacs-lisp/byte-opt.el
@@ -1509,7 +1509,7 @@ byte-compile-side-effect-and-error-free-ops
byte-current-buffer byte-stack-ref))
(defconst byte-compile-side-effect-free-ops
- (nconc
+ (append
'(byte-varref byte-nth byte-memq byte-car byte-cdr byte-length byte-aref
byte-symbol-value byte-get byte-concat2 byte-concat3 byte-sub1 byte-add1
byte-eqlsign byte-gtr byte-lss byte-leq byte-geq byte-diff byte-negate
diff --git a/lisp/frameset.el b/lisp/frameset.el
index 10c6914f52..0462d776c0 100644
--- a/lisp/frameset.el
+++ b/lisp/frameset.el
@@ -396,17 +396,17 @@ frameset-prop
;; or, if you're only changing a few items,
;;
;; (defvar my-filter-alist
-;; (nconc '((my-param1 . :never)
-;; (my-param2 . my-filtering-function))
-;; frameset-filter-alist)
+;; (append '((my-param1 . :never)
+;; (my-param2 . my-filtering-function))
+;; frameset-filter-alist)
;; "My brief customized parameter filter alist.")
;;
;; and pass it to the FILTER arg of the save/restore functions,
;; ALWAYS taking care of not modifying the original lists; if you're
;; going to do any modifying of my-filter-alist, please use
;;
-;; (nconc '((my-param1 . :never) ...)
-;; (copy-sequence frameset-filter-alist))
+;; (append '((my-param1 . :never) ...)
+;; (copy-sequence frameset-filter-alist))
;;
;; One thing you shouldn't forget is that they are alists, so searching
;; in them is sequential. If you just want to change the default of
@@ -445,7 +445,7 @@ frameset-session-filter-alist
;;;###autoload
(defvar frameset-persistent-filter-alist
- (nconc
+ (append
'((background-color . frameset-filter-sanitize-color)
(buffer-list . :never)
(buffer-predicate . :never)
diff --git a/lisp/gnus/gnus-sum.el b/lisp/gnus/gnus-sum.el
index 6f367692dd..341f04ad77 100644
--- a/lisp/gnus/gnus-sum.el
+++ b/lisp/gnus/gnus-sum.el
@@ -1501,9 +1501,9 @@ gnus-summary-mode-line-format-alist
;; This is here rather than in gnus-art for compilation reasons.
(defvar gnus-article-mode-line-format-alist
- (nconc '((?w (gnus-article-wash-status) ?s)
- (?m (gnus-article-mime-part-status) ?s))
- gnus-summary-mode-line-format-alist))
+ (append '((?w (gnus-article-wash-status) ?s)
+ (?m (gnus-article-mime-part-status) ?s))
+ gnus-summary-mode-line-format-alist))
(defvar gnus-last-search-regexp nil
"Default regexp for article search command.")
diff --git a/lisp/language/japanese.el b/lisp/language/japanese.el
index d77efa48c9..9a99245dfd 100644
--- a/lisp/language/japanese.el
+++ b/lisp/language/japanese.el
@@ -82,9 +82,7 @@ 'iso-2022-jp-2
(#x00A6 . #xFFE4) ; BROKEN LINE FULLWIDTH BROKEN LINE
)))
(define-translation-table 'japanese-ucs-jis-to-cp932-map map)
- (mapc #'(lambda (x) (let ((tmp (car x)))
- (setcar x (cdr x)) (setcdr x tmp)))
- map)
+ (setq map (mapcar (lambda (x) (cons (cdr x) (car x))) map))
(define-translation-table 'japanese-ucs-cp932-to-jis-map map))
;; U+2014 (EM DASH) vs U+2015 (HORIZONTAL BAR)
@@ -241,8 +239,10 @@ 'shift_jis-2004
(#x2b65 . [#x02E9 #x02E5])
(#x2b66 . [#x02E5 #x02E9])))
table)
- (dolist (elt map)
- (setcar elt (decode-char 'japanese-jisx0213-1 (car elt))))
+ (setq map
+ (mapcar (lambda (x) (cons (decode-char 'japanese-jisx0213-1 (car x))
+ (cdr x)))
+ map))
(setq table (make-translation-table-from-alist map))
(define-translation-table 'jisx0213-to-unicode table)
(define-translation-table 'unicode-to-jisx0213
diff --git a/lisp/language/lao-util.el b/lisp/language/lao-util.el
index a20aecee42..fa4c2f7f89 100644
--- a/lisp/language/lao-util.el
+++ b/lisp/language/lao-util.el
@@ -183,7 +183,9 @@ lao-compose-string
;; Semi-vowel-sign-lo and lower vowels are put under the letter.
(defconst lao-transcription-consonant-alist
- (sort '(;; single consonants
+ (sort
+ (copy-sequence
+ '(;; single consonants
("k" . "ກ")
("kh" . "ຂ")
("qh" . "ຄ")
@@ -223,14 +225,16 @@ lao-transcription-consonant-alist
("hy" . ["ຫຍ"])
("hn" . ["ຫນ"])
("hm" . ["ຫມ"])
- )
- (function (lambda (x y) (> (length (car x)) (length (car y)))))))
+ ))
+ (lambda (x y) (> (length (car x)) (length (car y))))))
(defconst lao-transcription-semi-vowel-alist
'(("r" . "ຼ")))
(defconst lao-transcription-vowel-alist
- (sort '(("a" . "ະ")
+ (sort
+ (copy-sequence
+ '(("a" . "ະ")
("ar" . "າ")
("i" . "ິ")
("ii" . "ີ")
@@ -257,8 +261,8 @@ lao-transcription-vowel-alist
("ai" . "ໄ")
("ei" . "ໃ")
("ao" . ["ເົາ"])
- ("aM" . "ຳ"))
- (function (lambda (x y) (> (length (car x)) (length (car y)))))))
+ ("aM" . "ຳ")))
+ (lambda (x y) (> (length (car x)) (length (car y))))))
;; Maa-sakod is put at the tail.
(defconst lao-transcription-maa-sakod-alist
diff --git a/lisp/language/tibetan.el b/lisp/language/tibetan.el
index d31cd5cd52..bbd4729f6c 100644
--- a/lisp/language/tibetan.el
+++ b/lisp/language/tibetan.el
@@ -326,7 +326,9 @@ tibetan-precomposed-transcription-alist
(defconst tibetan-subjoined-transcription-alist
- (sort '(("+k" . "ྐ")
+ (sort
+ (copy-sequence
+ '(("+k" . "ྐ")
("+kh" . "ྑ")
("+g" . "ྒ")
("+gh" . "ྒྷ")
@@ -371,8 +373,8 @@ tibetan-subjoined-transcription-alist
("+W" . "ྺ") ;; fixed form subscribed WA
("+Y" . "ྻ") ;; fixed form subscribed YA
("+R" . "ྼ") ;; fixed form subscribed RA
- )
- (lambda (x y) (> (length (car x)) (length (car y))))))
+ ))
+ (lambda (x y) (> (length (car x)) (length (car y))))))
;;;
;;; alist for Tibetan base consonant <-> subjoined consonant conversion.
diff --git a/test/src/fns-tests.el b/test/src/fns-tests.el
index c6ceae4a00..b65543a64b 100644
--- a/test/src/fns-tests.el
+++ b/test/src/fns-tests.el
@@ -49,21 +49,21 @@ fns-tests-nreverse
(should-error (nreverse))
(should-error (nreverse 1))
(should-error (nreverse (make-char-table 'foo)))
- (should (equal (nreverse "xyzzy") "yzzyx"))
- (let ((A []))
+ (should (equal (nreverse (copy-sequence "xyzzy")) "yzzyx"))
+ (let ((A (vector)))
(nreverse A)
(should (equal A [])))
- (let ((A [0]))
+ (let ((A (vector 0)))
(nreverse A)
(should (equal A [0])))
- (let ((A [1 2 3 4]))
+ (let ((A (vector 1 2 3 4)))
(nreverse A)
(should (equal A [4 3 2 1])))
- (let ((A [1 2 3 4]))
+ (let ((A (vector 1 2 3 4)))
(nreverse A)
(nreverse A)
(should (equal A [1 2 3 4])))
- (let* ((A [1 2 3 4])
+ (let* ((A (vector 1 2 3 4))
(B (nreverse (nreverse A))))
(should (equal A B))))
@@ -146,13 +146,13 @@ fns-tests-collate-strings
;; Invalid UTF-8 sequences shall be indicated. How to create such strings?
(ert-deftest fns-tests-sort ()
- (should (equal (sort '(9 5 2 -1 5 3 8 7 4) (lambda (x y) (< x y)))
+ (should (equal (sort (list 9 5 2 -1 5 3 8 7 4) (lambda (x y) (< x y)))
'(-1 2 3 4 5 5 7 8 9)))
- (should (equal (sort '(9 5 2 -1 5 3 8 7 4) (lambda (x y) (> x y)))
+ (should (equal (sort (list 9 5 2 -1 5 3 8 7 4) (lambda (x y) (> x y)))
'(9 8 7 5 5 4 3 2 -1)))
- (should (equal (sort '[9 5 2 -1 5 3 8 7 4] (lambda (x y) (< x y)))
+ (should (equal (sort (vector 9 5 2 -1 5 3 8 7 4) (lambda (x y) (< x y)))
[-1 2 3 4 5 5 7 8 9]))
- (should (equal (sort '[9 5 2 -1 5 3 8 7 4] (lambda (x y) (> x y)))
+ (should (equal (sort (vector 9 5 2 -1 5 3 8 7 4) (lambda (x y) (> x y)))
[9 8 7 5 5 4 3 2 -1]))
(should (equal
(sort
@@ -172,7 +172,7 @@ fns-tests-collate-sort
;; Punctuation and whitespace characters are relevant for POSIX.
(should
(equal
- (sort '("11" "12" "1 1" "1 2" "1.1" "1.2")
+ (sort (list "11" "12" "1 1" "1 2" "1.1" "1.2")
(lambda (a b) (string-collate-lessp a b "POSIX")))
'("1 1" "1 2" "1.1" "1.2" "11" "12")))
;; Punctuation and whitespace characters are not taken into account
@@ -180,7 +180,7 @@ fns-tests-collate-sort
(when (eq system-type 'windows-nt)
(should
(equal
- (sort '("11" "12" "1 1" "1 2" "1.1" "1.2")
+ (sort (list "11" "12" "1 1" "1 2" "1.1" "1.2")
(lambda (a b)
(let ((w32-collate-ignore-punctuation t))
(string-collate-lessp
@@ -190,7 +190,7 @@ fns-tests-collate-sort
;; Diacritics are different letters for POSIX, they sort lexicographical.
(should
(equal
- (sort '("Ævar" "Agustín" "Adrian" "Eli")
+ (sort (list "Ævar" "Agustín" "Adrian" "Eli")
(lambda (a b) (string-collate-lessp a b "POSIX")))
'("Adrian" "Agustín" "Eli" "Ævar")))
;; Diacritics are sorted between similar letters for other locales,
@@ -198,7 +198,7 @@ fns-tests-collate-sort
(when (eq system-type 'windows-nt)
(should
(equal
- (sort '("Ævar" "Agustín" "Adrian" "Eli")
+ (sort (list "Ævar" "Agustín" "Adrian" "Eli")
(lambda (a b)
(let ((w32-collate-ignore-punctuation t))
(string-collate-lessp
@@ -212,7 +212,7 @@ fns-tests-string-version-lessp
(should (not (string-version-lessp "foo20000.png" "foo12.png")))
(should (string-version-lessp "foo.png" "foo2.png"))
(should (not (string-version-lessp "foo2.png" "foo.png")))
- (should (equal (sort '("foo12.png" "foo2.png" "foo1.png")
+ (should (equal (sort (list "foo12.png" "foo2.png" "foo1.png")
'string-version-lessp)
'("foo1.png" "foo2.png" "foo12.png")))
(should (string-version-lessp "foo2" "foo1234"))
@@ -432,9 +432,9 @@ fns-tests-mapcan
(should-error (mapcan))
(should-error (mapcan #'identity))
(should-error (mapcan #'identity (make-char-table 'foo)))
- (should (equal (mapcan #'list '(1 2 3)) '(1 2 3)))
+ (should (equal (mapcan #'list (list 1 2 3)) '(1 2 3)))
;; `mapcan' is destructive
- (let ((data '((foo) (bar))))
+ (let ((data (list (list 'foo) (list 'bar))))
(should (equal (mapcan #'identity data) '(foo bar)))
(should (equal data '((foo bar) (bar))))))
--
2.17.1
^ permalink raw reply related [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-12 1:59 ` Dmitry Gutov
@ 2020-05-17 1:28 ` Paul Eggert
2020-05-17 5:02 ` Michael Heerdegen
2020-05-17 12:39 ` Dmitry Gutov
0 siblings, 2 replies; 170+ messages in thread
From: Paul Eggert @ 2020-05-17 1:28 UTC (permalink / raw)
To: Dmitry Gutov
Cc: Michael Heerdegen, ke.vigouroux, 40671, Mattias Engdegård,
Richard Stallman
[-- Attachment #1: Type: text/plain, Size: 2599 bytes --]
On 5/11/20 6:59 PM, Dmitry Gutov wrote:
> I think that's exactly what a "constraint" means: something that is enforced.
Not necessarily. In some software systems constraints are not enforced. (Use
Google to search for "unenforced constraints", which can be quite the thing in
the database world.) But I am straying from the documentation issue.
> The symbol-name example? I'm not sure it's really important to
> warn about this one in particular.
OK, but then you also write:
> When one tries to
> describe "unsafe" things to do, they don't just give a few examples, they
> usually try to cover all cases.
... and symbol-name is one of the cases.
As far as the bigger project (cover all the cases) goes, I don't know how
feasible that would be. I suppose someone could take that on as a further task.
In the attached patch I did add one more example, of calling the copy-sequence
function, but there would be lots more examples where that came from.
> Inventing a name for such values doesn't help if the user doesn't have enough
> knowledge to avoid all members of this set. Or is "part of an expression that is
> evaluated" after all the test we'll be teaching?
No, it's not the only way that something can be a constant. This is why the
(symbol-name 'cons) example is relevant: it yields a string that has never been
"part of an expression that is evaluated".
> By the way, I have read last two paragraphs of that section now. C and
> "constants" are still there.
It's appropriate to talk about constants in the footnote that mentions languages
that have constants. And the footnote is helpful, because it documents the core
issue that prompted this long thread: different languages/traditions mean
different things by the word "constant" and/or "immutable", and the footnote
makes it clear that the documentation's "objects that should not be changed"
follows the Common Lisp / C tradition, not the Python / JavaScript tradition.
That being said, it'd be helpful if the footnote mentions both "constants" and
"immutable objects" if only to remind readers of relevant buzzwords. So I did
that in the attached patch.
> I'm curious to see the discussion about actually making this error at runtime in
> one of the next Emacs version.
Me too. That's for a later thread, one that I'd like to get rolling instead of
worrying about the minor details in the current doc. To help get things rolling
I installed the patch that I proposed earlier, followed by the attached minor
patch that attempt to address the abovementioned issues. I plan to look at
improving the runtime checking next.
[-- Attachment #2: 0001-Minor-fixups-for-mutability-doc.patch --]
[-- Type: text/x-patch, Size: 2686 bytes --]
From b48ab743a861b8041518ce7459bde51c3dd02ee0 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Sat, 16 May 2020 18:16:23 -0700
Subject: [PATCH] Minor fixups for mutability doc
* doc/lispref/objects.texi (Mutability): Minor fixups in
response to a comment by Dmitry Gutov (Bug#40671#477).
---
doc/lispref/objects.texi | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/doc/lispref/objects.texi b/doc/lispref/objects.texi
index 136213ad66..5c5f89eb43 100644
--- a/doc/lispref/objects.texi
+++ b/doc/lispref/objects.texi
@@ -2381,7 +2381,7 @@ that for two strings to be equal, they have the same text properties.
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,
+its contents. And 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.
@@ -2393,11 +2393,10 @@ point to somewhere else.
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.
+although @code{"cons"} and @code{(symbol-name 'cons)} both yield
+strings that should not be changed, @code{(copy-sequence "cons")} and
+@code{(make-string 3 ?a)} both yield mutable strings that can be
+changed via later calls to @code{aset}.
A mutable object stops being mutable if it is part of an expression
that is evaluated. For example:
@@ -2419,9 +2418,9 @@ becomes mutable afterwards.
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
+Common Lisp and C for constants, and this differs from 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
+error if a program attempts to change an immutable object. Ideally the Emacs
Lisp interpreter will evolve in latter direction.}
When similar constants occur as parts of a program, the Lisp
--
2.17.1
^ permalink raw reply related [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-17 1:28 ` Paul Eggert
@ 2020-05-17 5:02 ` Michael Heerdegen
2020-05-17 16:34 ` Paul Eggert
2020-05-17 12:39 ` Dmitry Gutov
1 sibling, 1 reply; 170+ messages in thread
From: Michael Heerdegen @ 2020-05-17 5:02 UTC (permalink / raw)
To: Paul Eggert
Cc: Mattias Engdegård, Dmitry Gutov, 40671, Richard Stallman,
ke.vigouroux
Paul Eggert <eggert@cs.ucla.edu> writes:
> ... and symbol-name is one of the cases.
I'm wondering about this one for a while, too. Is it that the resulting
string is really like the "object is part of an evaluated program"
cases, or is it just that modifying it has an unwanted side effect
(changing the name of the symbol, and Emacs doesn't handle this
correctly). I mean, you can modify a lot of objects in Emacs and that
will cause trouble. We surely don't want to call them all constant or
not safely mutable or whatever. How is the result of `symbol-name'
different from these other cases? Is it only that the side effect/ mess
is not visible from Lisp? Where do you draw the line? Yes, the hidden
question is still what your definition of safely mutable is.
Thanks,
Michael.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-17 0:11 ` Paul Eggert
@ 2020-05-17 9:43 ` Mattias Engdegård
2020-05-17 16:38 ` Paul Eggert
0 siblings, 1 reply; 170+ messages in thread
From: Mattias Engdegård @ 2020-05-17 9:43 UTC (permalink / raw)
To: Paul Eggert; +Cc: Michael Heerdegen, 40671
17 maj 2020 kl. 02.11 skrev Paul Eggert <eggert@cs.ucla.edu>:
> Thanks for sending that patch. Even if incomplete, it's better to not try to
> modify constants so I installed the attached into master; it's derived from your
> patch and supersedes my earlier (typo-containing) patch about nconc.
Thank you, and your resulting patch looks all right. As an extra check, I verified that the AWK-generated files result in the same tables.
The follow-up change reducing string and vector literal mutation also looks fine. Just out of curiosity, how did you locate those instances? By searching for calls to mutating functions or with an instrumented Emacs?
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-17 1:28 ` Paul Eggert
2020-05-17 5:02 ` Michael Heerdegen
@ 2020-05-17 12:39 ` Dmitry Gutov
2020-05-17 16:21 ` Paul Eggert
1 sibling, 1 reply; 170+ messages in thread
From: Dmitry Gutov @ 2020-05-17 12:39 UTC (permalink / raw)
To: Paul Eggert
Cc: Michael Heerdegen, ke.vigouroux, 40671, Mattias Engdegård,
Richard Stallman
On 17.05.2020 04:28, Paul Eggert wrote:
> On 5/11/20 6:59 PM, Dmitry Gutov wrote:
>
>> I think that's exactly what a "constraint" means: something that is enforced.
>
> Not necessarily. In some software systems constraints are not enforced. (Use
> Google to search for "unenforced constraints", which can be quite the thing in
> the database world.) But I am straying from the documentation issue.
An existence of a technical term doesn't really cancel out the regular
meaning of the word.
>> The symbol-name example? I'm not sure it's really important to
>> warn about this one in particular.
>
> OK, but then you also write:
>
>> When one tries to
>> describe "unsafe" things to do, they don't just give a few examples, they
>> usually try to cover all cases.
>
> ... and symbol-name is one of the cases.
These are just two distinct points:
1. You seem to be trying to redefine the term "motable" as a way to
avoid enumerating all possible cases. But since the meaning of the term
is different from how it is understood in the English language, it
should at least have a proper definition. But the said definition would
have to cover the possible cases too.
2. symbol-name seems like something we don't have to explain specially.
So if that's the only counter-example to "values that appear in
expressions", or whichever phrase we chose, then we could as well just
on the phrase and dispense with additional complications. Which would
also make having a redefinition of the term "mutable" less relevant.
> As far as the bigger project (cover all the cases) goes, I don't know how
> feasible that would be. I suppose someone could take that on as a further task.
> In the attached patch I did add one more example, of calling the copy-sequence
> function, but there would be lots more examples where that came from.
>
>> Inventing a name for such values doesn't help if the user doesn't have enough
>> knowledge to avoid all members of this set. Or is "part of an expression that is
>> evaluated" after all the test we'll be teaching?
>
> No, it's not the only way that something can be a constant. This is why the
> (symbol-name 'cons) example is relevant: it yields a string that has never been
> "part of an expression that is evaluated".
There's an argument to be made that the name of the symbol 'cons is part
of any expression or program that uses `cons'.
>> By the way, I have read last two paragraphs of that section now. C and
>> "constants" are still there.
>
> It's appropriate to talk about constants in the footnote that mentions languages
> that have constants. And the footnote is helpful, because it documents the core
> issue that prompted this long thread: different languages/traditions mean
> different things by the word "constant" and/or "immutable", and the footnote
> makes it clear that the documentation's "objects that should not be changed"
> follows the Common Lisp / C tradition, not the Python / JavaScript tradition.
>
> That being said, it'd be helpful if the footnote mentions both "constants" and
> "immutable objects" if only to remind readers of relevant buzzwords. So I did
> that in the attached patch.
I like that change, thank you.
>> I'm curious to see the discussion about actually making this error at runtime in
>> one of the next Emacs version.
>
> Me too. That's for a later thread, one that I'd like to get rolling instead of
> worrying about the minor details in the current doc. To help get things rolling
> I installed the patch that I proposed earlier, followed by the attached minor
> patch that attempt to address the abovementioned issues. I plan to look at
> improving the runtime checking next.
OK, thank you.
My intuition, though, that making cases like the one you just changed in
emacs-lisp-mode-tests.el blow up at runtime will create a massive
backward incompatibility.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-17 12:39 ` Dmitry Gutov
@ 2020-05-17 16:21 ` Paul Eggert
0 siblings, 0 replies; 170+ messages in thread
From: Paul Eggert @ 2020-05-17 16:21 UTC (permalink / raw)
To: Dmitry Gutov
Cc: Michael Heerdegen, ke.vigouroux, 40671, Mattias Engdegård,
Richard Stallman
On 5/17/20 5:39 AM, Dmitry Gutov wrote:
> An existence of a technical term doesn't really cancel out the regular meaning
> of the word.
I continue to be skeptical that "constraints are always enforced" is the regular
meaning of the word "constraints" in computing. Lots of constraints are not
enforced in the computing world. Internet RFCs are a classic example: "Be
liberal in what you accept" means "Don't enforce constraints".
But again, we are straying from the point at hand, as the word "constraints"
isn't used in the documentation when talking about mutability.
> 1. You seem to be trying to redefine the term "motable" as a way to avoid
> enumerating all possible cases.
That is a normal practice for definitions, and this practice increases the
utility of the documentation. The Emacs manual defines "string" without
enumering all possible cases of strings (whether they come from the program
text, or from reading input, or from symbol-name, etc.) because enumerating all
cases would be bloat that would cause more harm than good. Similarly, the manual
defines "mutable" without defining all possible cases of mutable objects.
> 2. symbol-name seems like something we don't have to explain specially.
I don't understand this comment. symbol-name is just an example. It's helpful to
have an example or two, even if they're not absolutely required.
> There's an argument to be made that the name of the symbol 'cons is part of any
> expression or program that uses `cons'.
Sure, and that argument is part of any bigger project to document more about
mutability ("covering all the cases" in some way). This would not be a trivial
project, and it's not something we have to do today.
> My intuition, though, that making cases like the one you just changed in emacs-lisp-mode-tests.el blow up at runtime will create a massive backward incompatibility.
I'm sure there are compatibility issues. But we already have those issues: an
Elisp program that modifies a string constant is already "broken" in that it's
making assumptions that have never been documented and are sometimes not true
even now. Emacs used to have some runtime checking for this bug but it doesn't
now, and when we reinstitute checking we will undoubtedly shake out some latent
bugs in user code.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-17 5:02 ` Michael Heerdegen
@ 2020-05-17 16:34 ` Paul Eggert
0 siblings, 0 replies; 170+ messages in thread
From: Paul Eggert @ 2020-05-17 16:34 UTC (permalink / raw)
To: Michael Heerdegen
Cc: Mattias Engdegård, Dmitry Gutov, 40671, Richard Stallman,
ke.vigouroux
On 5/16/20 10:02 PM, Michael Heerdegen wrote:
> you can modify a lot of objects in Emacs and that
> will cause trouble. We surely don't want to call them all constant or
> not safely mutable or whatever.
We may not *want* to do that, but that's what we're doing now (with the two
classes currently documented as "mutable objects" and "objects that you should
not change"). And I don't see any easy way to change the documentation to draw
the line that we'd like to draw (namely, between "mutable objects" and "objects
that you cannot change") because that's not how Emacs works and changing Emacs's
behavior will be nontrivial.
At this point I suspect it'll be a better of our time to look into improving
Emacs's behavior in this area, and worry about documentation wording later.
^ permalink raw reply [flat|nested] 170+ messages in thread
* bug#40671: [DOC] modify literal objects
2020-05-17 9:43 ` Mattias Engdegård
@ 2020-05-17 16:38 ` Paul Eggert
0 siblings, 0 replies; 170+ messages in thread
From: Paul Eggert @ 2020-05-17 16:38 UTC (permalink / raw)
To: Mattias Engdegård; +Cc: Michael Heerdegen, 40671
On 5/17/20 2:43 AM, Mattias Engdegård wrote:
> how did you locate those instances? By searching for calls to mutating functions or with an instrumented Emacs?
I built an instrumented Emacs. I am working on making it faster, since I don't
want the extra runtime checks to cost so much that people would prefer sticking
with the current, sometimes-crashing Emacs.
^ permalink raw reply [flat|nested] 170+ messages in thread
end of thread, other threads:[~2020-05-17 16:38 UTC | newest]
Thread overview: 170+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-04-16 19:28 bug#40671: [DOC] modify literal objects Kevin Vigouroux via Bug reports for GNU Emacs, the Swiss army knife of text editors
2020-04-17 16:09 ` Mattias Engdegård
2020-04-17 16:37 ` Mattias Engdegård
2020-04-17 17:27 ` Eli Zaretskii
2020-04-18 20:10 ` Paul Eggert
2020-04-18 21:54 ` Drew Adams
2020-04-19 2:39 ` Noam Postavsky
2020-04-19 20:39 ` Paul Eggert
2020-04-19 21:01 ` Drew Adams
2020-04-19 21:16 ` Paul Eggert
2020-04-19 22:24 ` Drew Adams
2020-04-19 22:51 ` Paul Eggert
2020-04-20 5:32 ` Drew Adams
2020-04-22 17:36 ` Paul Eggert
2020-05-01 3:03 ` Dmitry Gutov
2020-05-01 5:16 ` Drew Adams
2020-05-01 21:46 ` Paul Eggert
2020-05-01 23:37 ` Dmitry Gutov
2020-04-19 2:26 ` Richard Stallman
2020-04-19 13:56 ` Eli Zaretskii
2020-04-19 16:59 ` Mattias Engdegård
2020-04-19 19:21 ` Eli Zaretskii
2020-04-19 21:02 ` Paul Eggert
2020-04-19 21:11 ` Drew Adams
2020-04-19 21:57 ` Michael Heerdegen
2020-04-19 22:41 ` Paul Eggert
2020-04-19 23:45 ` Michael Heerdegen
2020-04-20 0:24 ` Paul Eggert
2020-04-20 0:53 ` Michael Heerdegen
2020-04-20 3:23 ` Paul Eggert
2020-04-20 3:36 ` Michael Heerdegen
2020-04-22 6:30 ` Paul Eggert
2020-04-20 5:54 ` Drew Adams
2020-04-22 17:21 ` Paul Eggert
2020-04-23 0:49 ` Michael Heerdegen
2020-04-24 2:36 ` Richard Stallman
2020-04-24 15:08 ` Drew Adams
2020-04-25 1:58 ` Paul Eggert
2020-04-24 16:39 ` Mattias Engdegård
2020-04-24 16:46 ` Dmitry Gutov
2020-04-25 2:21 ` Paul Eggert
2020-04-25 2:40 ` Dmitry Gutov
2020-04-25 3:20 ` Paul Eggert
2020-04-25 19:30 ` Dmitry Gutov
2020-04-26 3:49 ` Paul Eggert
2020-04-26 14:03 ` Dmitry Gutov
2020-04-26 14:19 ` Eli Zaretskii
2020-04-26 14:34 ` Dmitry Gutov
2020-04-26 15:46 ` Eli Zaretskii
2020-04-26 16:02 ` Dmitry Gutov
2020-04-26 16:58 ` Eli Zaretskii
2020-04-26 17:39 ` Dmitry Gutov
2020-04-26 18:14 ` Eli Zaretskii
2020-04-26 18:32 ` Dmitry Gutov
2020-04-26 18:41 ` Eli Zaretskii
2020-04-26 18:53 ` Dmitry Gutov
2020-04-26 18:57 ` Paul Eggert
2020-04-26 19:22 ` Philipp Stephani
2020-04-26 20:14 ` Paul Eggert
2020-04-26 21:23 ` Dmitry Gutov
2020-04-26 23:13 ` Paul Eggert
2020-04-27 0:53 ` Dmitry Gutov
2020-04-27 1:49 ` Paul Eggert
2020-04-28 3:05 ` Dmitry Gutov
2020-04-28 8:17 ` Paul Eggert
2020-04-28 13:54 ` Dmitry Gutov
2020-04-28 17:59 ` Paul Eggert
2020-04-28 18:46 ` Dmitry Gutov
2020-04-28 19:20 ` Paul Eggert
2020-04-28 19:33 ` Dmitry Gutov
2020-04-28 20:09 ` Paul Eggert
2020-04-28 21:10 ` Dmitry Gutov
2020-04-28 23:10 ` Paul Eggert
2020-04-28 23:36 ` Dmitry Gutov
2020-04-28 23:53 ` Paul Eggert
2020-04-28 23:57 ` Dmitry Gutov
2020-04-28 23:53 ` Dmitry Gutov
2020-04-29 0:04 ` Paul Eggert
2020-04-29 0:14 ` Dmitry Gutov
2020-04-29 0:55 ` Drew Adams
2020-04-29 1:03 ` Dmitry Gutov
2020-04-29 1:15 ` Drew Adams
2020-04-29 1:27 ` Michael Heerdegen
2020-04-29 1:38 ` Paul Eggert
2020-04-29 4:36 ` Drew Adams
2020-04-29 16:18 ` Paul Eggert
2020-05-01 2:47 ` Richard Stallman
2020-05-01 6:23 ` Eli Zaretskii
2020-05-01 3:13 ` Dmitry Gutov
2020-05-01 5:15 ` Drew Adams
2020-05-01 21:40 ` Paul Eggert
2020-05-01 22:05 ` Drew Adams
2020-05-01 22:28 ` Paul Eggert
2020-05-02 1:07 ` Dmitry Gutov
2020-05-02 6:28 ` Paul Eggert
2020-05-02 15:42 ` Dmitry Gutov
2020-05-02 19:35 ` Paul Eggert
2020-05-03 1:30 ` Dmitry Gutov
2020-05-03 7:40 ` Paul Eggert
2020-05-03 16:44 ` Dmitry Gutov
2020-05-03 20:48 ` Paul Eggert
2020-05-03 22:17 ` Dmitry Gutov
2020-05-03 22:18 ` Dmitry Gutov
2020-05-03 22:39 ` Paul Eggert
2020-05-03 22:53 ` Dmitry Gutov
2020-05-03 23:10 ` Paul Eggert
2020-05-04 10:16 ` Dmitry Gutov
2020-05-04 17:52 ` Paul Eggert
2020-05-05 1:39 ` Dmitry Gutov
2020-05-05 6:09 ` Paul Eggert
2020-05-05 12:38 ` Dmitry Gutov
2020-05-09 6:10 ` Paul Eggert
2020-05-10 3:13 ` Dmitry Gutov
2020-05-10 13:34 ` Dmitry Gutov
2020-05-10 17:29 ` Paul Eggert
2020-05-11 0:00 ` Michael Heerdegen
2020-05-11 0:26 ` Dmitry Gutov
2020-05-11 1:47 ` Drew Adams
2020-05-11 1:54 ` Dmitry Gutov
2020-05-11 2:33 ` Drew Adams
2020-05-11 2:56 ` Michael Heerdegen
2020-05-11 4:21 ` Drew Adams
2020-05-11 4:51 ` Michael Heerdegen
2020-05-11 6:28 ` Paul Eggert
2020-05-11 13:57 ` Noam Postavsky
2020-05-11 22:36 ` Michael Heerdegen
2020-05-11 22:30 ` Michael Heerdegen
2020-05-12 3:20 ` Richard Stallman
2020-05-12 4:24 ` Michael Heerdegen
2020-05-13 3:57 ` Richard Stallman
2020-05-13 5:05 ` Michael Heerdegen
2020-05-14 5:14 ` Richard Stallman
[not found] ` <05BEF593-F16A-4DEE-98BC-653221F1F9EE@acm.org>
2020-05-17 0:11 ` Paul Eggert
2020-05-17 9:43 ` Mattias Engdegård
2020-05-17 16:38 ` Paul Eggert
2020-05-11 1:53 ` Paul Eggert
2020-05-11 3:18 ` Michael Heerdegen
2020-05-11 0:44 ` Dmitry Gutov
2020-05-11 1:57 ` Paul Eggert
2020-05-12 1:59 ` Dmitry Gutov
2020-05-17 1:28 ` Paul Eggert
2020-05-17 5:02 ` Michael Heerdegen
2020-05-17 16:34 ` Paul Eggert
2020-05-17 12:39 ` Dmitry Gutov
2020-05-17 16:21 ` Paul Eggert
2020-05-05 17:40 ` Drew Adams
2020-05-05 18:49 ` Dmitry Gutov
2020-05-05 19:26 ` Drew Adams
2020-05-05 20:48 ` Kevin Vigouroux via Bug reports for GNU Emacs, the Swiss army knife of text editors
2020-05-09 5:57 ` Paul Eggert
2020-04-28 21:18 ` Dmitry Gutov
2020-04-28 17:25 ` Drew Adams
2020-04-28 17:47 ` Paul Eggert
2020-04-29 0:32 ` Michael Heerdegen
2020-04-29 1:40 ` Paul Eggert
2020-04-29 4:40 ` Michael Heerdegen
2020-04-29 8:01 ` Eli Zaretskii
2020-04-29 16:36 ` Paul Eggert
2020-04-24 17:18 ` Drew Adams
2020-04-25 3:38 ` Richard Stallman
2020-04-25 18:26 ` Paul Eggert
2020-04-25 2:22 ` Paul Eggert
2020-04-25 6:00 ` Andreas Schwab
2020-04-25 18:23 ` Paul Eggert
2020-04-28 23:52 ` Michael Heerdegen
2020-04-21 1:25 ` Michael Heerdegen
2020-04-21 2:20 ` Paul Eggert
2020-04-20 6:02 ` Drew Adams
2020-04-19 20:45 ` Paul Eggert
2020-04-20 14:10 ` Eli Zaretskii
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).