emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] fix/bug-31311-pcase-doc 977bd10 3/3: expand @item "Side-ef


From: Thien-Thi Nguyen
Subject: [Emacs-diffs] fix/bug-31311-pcase-doc 977bd10 3/3: expand @item "Side-effecting code..."
Date: Tue, 15 May 2018 10:31:42 -0400 (EDT)

branch: fix/bug-31311-pcase-doc
commit 977bd10f5e70c18019326f6df65e1de8c1ab26b0
Author: Thien-Thi Nguyen <address@hidden>
Commit: Thien-Thi Nguyen <address@hidden>

    expand @item "Side-effecting code..."
    
    - add example square-double-digit-p/{OK,WRONG}
    - list all places where evaluation occurs (i.e., all places
      in which it's ill-advised to use side-effecting references,
      i.e., EVERYWHERE :-D)
---
 doc/lispref/control.texi | 65 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 65 insertions(+)

diff --git a/doc/lispref/control.texi b/doc/lispref/control.texi
index 9044a2b..2e03ae0 100644
--- a/doc/lispref/control.texi
+++ b/doc/lispref/control.texi
@@ -635,6 +635,71 @@ On the other hand, B uses two separate symbols, @code{s1} 
and
 
 @item Side-effecting code referencing @var{symbol} is undefined.
 Avoid.
+For example, here are two similar functions.
+Both use @code{and}, @var{symbol} and @code{guard}:
+
address@hidden
address@hidden
+(defun square-double-digit-p/OK (integer)
+  (pcase (* integer integer)
+    ((and n (guard (< 9 n 100))) (list 'yes n))
+    (sorry (list 'no sorry))))
+
+(square-double-digit-p/OK 9) @result{} (yes 81)
+(square-double-digit-p/OK 3) @result{} (no 9)
address@hidden group
+
address@hidden
+(defun square-double-digit-p/WRONG (integer)
+  (pcase (* integer integer)
+    ((and n (guard (< 9 (incf n) 100))) (list 'yes n))
+    (sorry (list 'no sorry))))
+
+(square-double-digit-p/WRONG 9) @result{} (yes 81)
+(square-double-digit-p/WRONG 3) @result{} (yes 9)
address@hidden group
address@hidden example
+
address@hidden
+The difference is in @var{boolean-expression}:
address@hidden references @code{n} simply and directly,
+while @code{WRONG} references @code{n} with a side-effect,
+in the expression @code{(incf n)}.
+When @code{integer} is 3, here's what happens:
+
address@hidden
address@hidden The first @code{n} binds it to @var{expval},
+i.e., the result of evaluating @code{(* 3 3)}, or 9.
+
address@hidden @var{boolean-expression} is evaluated:
+
address@hidden
+start:   (< 9 (incf n)        100)
+becomes: (< 9 (setq n (1+ n)) 100)
+becomes: (< 9 (setq n (1+ 9)) 100)
+becomes: (< 9 (setq n 10)     100)
+                                   ; @r{side-effect here!}
+becomes: (< 9       n         100) ; @address@hidden now bound to 10}
+becomes: (< 9      10         100)
+becomes: t
address@hidden example
+
address@hidden Because the result of the evaluation is @code{t},
address@hidden matches, @code{and} matches, and
+control passes to that clause's body forms.
address@hidden itemize
+
address@hidden
+Aside from the mathematical incorrectness of asserting that 9 is a
+double-digit integer, there is another problem with @code{WRONG}.
+The body form references @code{n} once more, yet we do not see
+the updated value---10---at all.  What happened to it?
+
+To sum up, it's best to avoid side-effecting references to
address@hidden patterns entirely, not only
+in @var{boolean-expression} (in @code{guard}),
+but also in @var{expr} (in @code{let})
+and @var{function} (in @code{pred} and @code{app}).
 
 @item address@hidden should all bind the same symbols'' (from @code{or}).
 @c (what does it mean?)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]