branch: elpa/loopy
commit 1e76027423c791614c2ddafb18816ccf4317ea09
Author: okamsn <[email protected]>
Commit: GitHub <[email protected]>

    Reorganize documentation on accumulation commands and improve CHANGELOG. 
(#248)
    
    - In `loopy-doc.org`, try to make the different topics in Accumulation 
(before
      the sub-sections) read a bit more cleanly and flow better.
    
    - In `CHANGELOG.md`, make it clear what changed about modifying 
`loopy-result`
      in `finally-do`.
---
 CHANGELOG.md      |  40 ++++---
 doc/loopy-doc.org | 216 ++++++++++++++++---------------------
 doc/loopy.texi    | 313 +++++++++++++++++++++++-------------------------------
 tests/tests.el    |  20 ++++
 4 files changed, 268 insertions(+), 321 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index cc8cdaf9430..51fc91b5c3c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -47,22 +47,25 @@ For Loopy Dash, see <https://github.com/okamsn/loopy-dash>.
   ([#234], [#240]).  The old implementation used the name of the command in the
   generated code and was written before aliases.
 
-- `finally-do` can now modify the implied return value of a loopy by modifying
-  the implied accumulation variable, which is by default `loopy-result`
-  ([#244]).  Previously, one would have needed to use `finally-return` after
-  modifying an implied `loopy-result`.
-
-  This improves consistency by allowing treating an implied `loopy-result`
-  more like other, explicit accumulation variables inside `finally-do`.
-  The cost is switching from the use of `prog1` to an `if` expression with two
-  helper variables.  This change only applies when an implied return value is
-  used with `finally-do`.  It does not affect the macro expansion when
-  `finally-return` is used.
-
-  This is technically a breaking change for those who were modifying an implied
-  `loopy-result` but did not wish those changes to be captured in the macro's
-  implied return value nor used in `finally-return` (perhaps changing the value
-  for side effects only).
+- The macro by default now uses the value of `loopy-result` as the implied
+  return value when `loopy-result` is used as an implied accumulation variable
+  and `finally-do` is used ([#244]).  Previously, the macro would store the
+  implied return value in `loopy-result` when `loopy-result` was used as an
+  implied accumulation variable, but any further changes made to `loopy-result`
+  after the loop completed in the `finally-do` special macro argument
+  would not be included in the macro's ultimate return value.
+
+  This was inconsistent with modifying `loopy-result` in the `after-do` special
+  macro argument, in which case the modification /was/ included in the implied
+  return value.
+
+  The new behavior should be less confusing in the event that a user does 
modify
+  `loopy-result` in `finally-do`. Previously, one would have needed to use
+  `finally-return` after modifying an implied `loopy-result`. The cost is
+  switching from the use of `prog1` to an `if` expression with two helper
+  variables.  This change only applies when an implied return value is used 
with
+  `finally-do`.  It does not affect the macro expansion when `finally-return` 
is
+  used.
 
   ```emacs-lisp
   ;; Previously required way:
@@ -79,6 +82,11 @@ For Loopy Dash, see <https://github.com/okamsn/loopy-dash>.
          (finally-do (push 0 loopy-result)))
   ```
 
+  This is technically a breaking change for those who were modifying an implied
+  `loopy-result` but did not wish those changes to be captured in the macro's
+  implied return value nor used in `finally-return` (perhaps changing the value
+  for side effects only).
+
 - `loopy-default-flags` is now deprecated ([#245]).  This prevents one library
   from breaking the macro expansions in another library.  Instead of using
   `loopy-default-flags`, one should use a wrapping macro like the one below
diff --git a/doc/loopy-doc.org b/doc/loopy-doc.org
index 8f893b99ba6..b01e1a2d6a1 100644
--- a/doc/loopy-doc.org
+++ b/doc/loopy-doc.org
@@ -64,7 +64,7 @@ libraries =seq= ([[info:elisp#Sequence Functions]]) and 
=cl-lib= ([[info:cl]])).
     - [[#sequence-index-iteration][Sequence Index Iteration]]
     - [[#sequence-reference-iteration][Sequence Reference Iteration]]
   - [[#accumulation][Accumulation]]
-    - [[#common-properties-of-accumulation-commands][Common Properties of 
Accumulation Commands]]
+    - [[#common-properties-and-arguments-of-accumulation-commands][Common 
Properties and Arguments of Accumulation Commands]]
     - [[#generic-accumulation][Generic Accumulation]]
     - [[#numeric-accumulation][Numeric Accumulation]]
     - [[#sequence-accumulation][Sequence Accumulation]]
@@ -2827,10 +2827,12 @@ accumulated, instead of the destructured value.
 
 #+cindex: implied accumulation results
 Like in ~cl-loop~, you do not need to supply a variable name to accumulation
-commands.  If no accumulation variable is given, then the accumulated value is
-understood to be the return value of the loop.  These implied return values can
-be overridden by using the the =return= and =return-from= loop commands or the
-=finally-return= macro argument.
+commands.  If no accumulation variable is given and the =finally-do= special
+macro argument is not used, then the accumulated value is understood to be the
+return value of the loop.  Such a return value is described in this document as
+an {{{dfn(implied return value)}}} or an {{{dfn(implicit return value)}}}.  An
+implied return value can be overridden by using the the =return= and
+=return-from= loop commands or the =finally-return= macro argument.
 
 #+begin_src emacs-lisp
   ;; => (1 2 3)
@@ -2844,7 +2846,9 @@ be overridden by using the the =return= and =return-from= 
loop commands or the
 
 #+vindex: loopy-result
 Unlike ~cl-loop~, Loopy uses a default accumulation variable, which is named
-~loopy-result~.  This variable can be used in the =after-do=, =finally-do=, and
+~loopy-result~.  When used this way, ~loopy-result~ is described as an
+{{{dfn(implied accumulation variable)}}} or an {{{dfn(implicit accumulation
+variable)}}}.  This variable can be used in the =after-do=, =finally-do=, and
 =finally-return= special macro arguments.
 
 #+begin_src emacs-lisp
@@ -2854,25 +2858,83 @@ Unlike ~cl-loop~, Loopy uses a default accumulation 
variable, which is named
          (collect i)
          (finally-return (cons 0 loopy-result)))
 
+  ;; => (0 1 2 3)
+  (loopy (list i '(1 2 3))
+         (collect i)
+         (after-do (push 0 loopy-result)))
+
   ;; => (0 1 2 3)
   (loopy (list i '(1 2 3))
          (collect i)
          (finally-do (push 0 loopy-result)))
   #+end_src
 
-In general, you should not attempt to modify or use the value of ~loopy-result~
-during the loop when it is used as the implied accumulation variable for a
-command, as it is not guaranteed to have a correct value when efficiently
-building sequences.  For example, it is often faster to build a list in reverse
-instead of appending to its end.  For some commands, such as those in
-[[#accum-numeric]] and [[#accum-generic]], this does not matter.
+Like in ~cl-loop~, when multiple accumulation commands do not name an
+accumulation variable, they will all use the same implied accumulation variable
+(~loopy-result~).  As a consequence, one must explicitly name separate
+accumulation variables to be able to accumulate into separate values.  This can
+make accumulation slower, because ~loopy~ ensures that named accumulation
+variables (excluding the previously mentioned ~loopy-result~) have the correct
+value during the loop.  For example, ~loopy~ will construct named accumulation
+variables containing lists in the correct order, instead of using the more
+efficient ~push~-~nreverse~ idiom.  This behavior can be disabled by optimizing
+accumulation variables using the =accum-opt= special macro argument
+([[#optimized-accums]]).
+
+#+begin_src emacs-lisp
+  ;; Both command usages of `collect' and `append'
+  ;; use `loopy-result' as the implied accumulation variable:
+  ;;
+  ;; => (1 11 2 12 3 13)
+  (loopy (list i '(1 2 3))
+         (collect i)
+         (append (list (+ 10 i)) :at end)
+         (finally-return loopy-result))
+#+end_src
+
+In general, you should not attempt to modify or use the value of optimized
+accumulation variables during the loop, including ~loopy-result~ when it is 
used
+as the implied accumulation variable for a command, because they are not
+guaranteed to have a correct value when efficiently building sequences
+([[#optimized-accums]]).  For some commands, such as those listed in 
[[#accum-numeric]]
+and [[#accum-generic]], this does not matter.
+
+#+begin_src emacs-lisp
+  ;; See that `loopy-result' is not in the correct order during the loop
+  ;; (the exact value of an optimized accumulation variable during the loop
+  ;; is an implementation detail):
+  ;;
+  ;; => (6 5 4 3 2 1)
+  (loopy (number i :from 1 :to 10)
+         (collect i)
+         (when (> i 5)
+           (return loopy-result)))
+#+end_src
+
+Implied results are only required to be correct after the loop ends (before 
code
+in =else-do= is run).  Furthermore, because using a =return= or =return-from=
+command overrides implied return values, using these commands can prevent
+implied accumulation results from being finalized.  Using the =leave= command,
+which exits the loop without returning a value, does not affect the correctness
+of implied results.
+
+#+begin_src emacs-lisp
+  ;; See that the `leave' command does not prevent finalizing
+  ;; optimized accumulation variables, unlike the above `return' command:
+  ;;
+  ;; => (1 2 3 4 5 6)
+  (loopy (number i :from 1 :to 10)
+         (collect i)
+         (when (> i 5) (leave)))
+#+end_src
 
 Be aware that explicitly named accumulation variables do not affect the implied
 return value of a loop.  Such values must be returned explicitly, or they will
 be ignored when the macro returns a value.  This limitation is needed for more
 consistently handling the complexity that comes from allowing unknown kinds of
-destructuring via the alternative destructuring systems.  This may change in 
the
-future.
+destructuring via the alternative destructuring systems, such as the possibly
+intermediate variables that can be generated by ~pcase~ patterns.  This may
+change in the future.
 
 #+begin_src emacs-lisp
   ;; See how the variable `my-explicit-variable' is ignored when
@@ -2905,14 +2967,12 @@ accumulation results.
 #+end_src
 
 #+cindex: accumulation compatibility
-Like in ~cl-loop~, when using implied variables, multiple accumulation commands
-will use the same variable (~loopy-result~).  For _all_ accumulation variables
-used by multiple accumulation commands, you should make sure that the commands
-are actually compatible.  If not, then ~loopy~ will signal an error.
-
-For example, you should not try to accumulate =collect= results and =sum=
-results into the same variable, as you cannot use a list as a number.  On the
-other hand, =sum= and =multiply= are compatible, since they both act on 
numbers.
+For all accumulation variables used by multiple accumulation commands, you
+should make sure that the commands are actually compatible.  If not, then
+~loopy~ will signal an error.  For example, you should not try to accumulate
+=collect= results and =sum= results into the same variable, as you cannot use a
+list as a number.  On the other hand, =sum= and =multiply= are compatible, 
since
+they both act on numbers.
 
 #+begin_src emacs-lisp
   ;; Incompatible commands:
@@ -2930,12 +2990,13 @@ other hand, =sum= and =multiply= are compatible, since 
they both act on numbers.
 #+end_src
 
 #+cindex: accumulation initial values
-Each accumulation command has a default initialization value for the
-accumulation variable.  For most commands, this is ~nil~.  This documentation
-tries to note when it is not ~nil~.  For example, the default starting value 
for
-the =sum= command is ~0~ and the default starting value for the =multiply=
-command is ~1~.  The default initialization value used by an accumulation
-command can be overridden using the =with= special macro argument.
+In the same general area as accumulation command compatability, you should keep
+in mind that each accumulation command has a default initialization value for
+the accumulation variable.  For most commands, this is ~nil~.  This
+documentation tries to note when it is not ~nil~.  For example, the default
+starting value for the =sum= command is ~0~ and the default starting value for
+the =multiply= command is ~1~.  The default initialization value used by an
+accumulation command can be overridden using the =with= special macro argument.
 
 #+attr_texinfo: :tag Warning
 #+begin_quote
@@ -2963,104 +3024,7 @@ conflict, use the =with= special macro argument, as 
noted above.
          (finally-return my-accum))
 #+end_src
 
-One must specify separate accumulation variables to be able to accumulate into
-separate values.  This can make accumulation slower, because ~loopy~ ensures
-that named accumulation variables (excluding the previously mentioned
-~loopy-result~) have the correct value during the loop.  For example, ~loopy~
-will construct named accumulation variables containing lists in the correct
-order, instead of using the more efficient ~push~-~nreverse~ idiom.  This
-behavior can be disabled by optimizing accumulations using the =accum-opt=
-special macro argument ([[#optimized-accums]]).
-
-Below are examples of an optimized accumulation and an un-optimized
-accumulation.  See that the example expansion of the un-optimized accumulation
-is more complex and uses a slower way of building the accumulated list.
-
-#+begin_src emacs-lisp
-  ;; Optimized accumulation:
-  ;;
-  ;; => (1 3 2 6 3 9)
-  (loopy (accum-opt coll)
-         (numbers i :from 1 :to 3)
-         (collect coll i)
-         (collect coll (* i 3))
-         (finally-return coll))
-
-  ;; Optimized example expansion:
-  ;;
-  ;; => (1 3 2 6 3 9)
-  (let* ((coll nil)
-         (i 1)
-         (nums-end192 3)
-         (nums-increment191 1))
-    (cl-block nil
-      (while (<= i nums-end192)
-        (setq coll (cons i coll))
-        (setq coll (cons (* i 3) coll))
-        (setq i (1+ i)))
-      (setq coll (nreverse coll)))
-    coll)
-#+end_src
-
-#+begin_src emacs-lisp
-  ;; Unoptimized accumulation:
-  ;;
-  ;; => (1 3 2 6 3 9)
-  (loopy (numbers i :from 1 :to 3)
-         (collect coll i)
-         (collect coll (* i 3))
-         (finally-return coll))
-
-  ;; Unoptimized example expansion:
-  ;;
-  ;; => (1 3 2 6 3 9)
-  (let* ((coll nil)
-         (coll-last-link-190 coll)
-         (i 1)
-         (nums-end189 3)
-         (nums-increment188 1))
-    (cl-block nil
-      (while (<= i nums-end189)
-        (cond
-         (coll-last-link-190
-          (setcdr coll-last-link-190 (list i))
-          (setq coll-last-link-190 (cdr coll-last-link-190)))
-         (coll
-          (setq coll-last-link-190 (last coll))
-          (setcdr coll-last-link-190 (list i))
-          (setq coll-last-link-190 (cdr coll-last-link-190)))
-         (t
-          (setq coll (list i)
-                coll-last-link-190 coll)))
-        (cond
-         (coll-last-link-190
-          (setcdr coll-last-link-190 (list (* i 3)))
-          (setq coll-last-link-190 (cdr coll-last-link-190)))
-         (coll
-          (setq coll-last-link-190 (last coll))
-          (setcdr coll-last-link-190 (list (* i 3)))
-          (setq coll-last-link-190 (cdr coll-last-link-190)))
-         (t
-          (setq coll (list (* i 3))
-                coll-last-link-190 coll)))
-        (setq i (1+ i))))
-    coll)
-#+end_src
-
-#+attr_texinfo: :tag Warning
-#+begin_quote
-In general, you should not try to access implied (or optimized) accumulation
-results (for example, ~loopy-result~) while the loop is running.  Implied
-results are only required to be correct after the loop ends (before code in
-=else-do= is run), allowing for more efficient code.
-
-Furthermore, because using a =return= or =return-from= command overrides 
implied
-return values, using these commands can prevent implied accumulation results
-from being finalized.  Using the =leave= command, which exits the loop without
-returning a value, does not affect the correctness of implied results.
-#+end_quote
-
-*** Common Properties of Accumulation Commands
+*** Common Properties and Arguments of Accumulation Commands
 :PROPERTIES:
 :END:
 
diff --git a/doc/loopy.texi b/doc/loopy.texi
index 7a0b4520529..4ed390af518 100644
--- a/doc/loopy.texi
+++ b/doc/loopy.texi
@@ -73,7 +73,7 @@ Iteration
 
 Accumulation
 
-* Common Properties of Accumulation Commands::
+* Common Properties and Arguments of Accumulation Commands::
 * Generic Accumulation::         Accumulating function output.
 * Numeric Accumulation::         Using and returning numbers.
 * Sequence Accumulation::        Using and returning sequences.
@@ -746,7 +746,7 @@ You should keep in mind that commands are evaluated in 
order.  This means that
 attempting something like the below example might not do what you expect, as 
@samp{i}
 is assigned a value from the list after collecting @samp{i} into @samp{coll}.
 
-@float Listing,org05823f8
+@float Listing,org572b5bd
 @lisp
 ;; => (nil 1 2)
 (loopy (collect coll i)
@@ -935,7 +935,7 @@ the flag @samp{dash} provided by the package 
@samp{loopy-dash}.
 
 Below are two examples of destructuring in @code{cl-loop} and @code{loopy}.
 
-@float Listing,org02ede57
+@float Listing,org99c53b0
 @lisp
 ;; => (1 2 3 4)
 (cl-loop for (i . j) in '((1 . 2) (3 . 4))
@@ -950,7 +950,7 @@ Below are two examples of destructuring in @code{cl-loop} 
and @code{loopy}.
 @caption{Destructuring values in a list.}
 @end float
 
-@float Listing,org9a7343f
+@float Listing,org7212adc
 @lisp
 ;; => (1 2 3 4)
 (cl-loop for elem in '((1 . 2) (3 . 4))
@@ -3037,10 +3037,12 @@ accumulated, instead of the destructured value.
 
 @cindex implied accumulation results
 Like in @code{cl-loop}, you do not need to supply a variable name to 
accumulation
-commands.  If no accumulation variable is given, then the accumulated value is
-understood to be the return value of the loop.  These implied return values can
-be overridden by using the the @samp{return} and @samp{return-from} loop 
commands or the
-@samp{finally-return} macro argument.
+commands.  If no accumulation variable is given and the @samp{finally-do} 
special
+macro argument is not used, then the accumulated value is understood to be the
+return value of the loop.  Such a return value is described in this document as
+an @dfn{implied return value} or an @dfn{implicit return value}.  An
+implied return value can be overridden by using the the @samp{return} and
+@samp{return-from} loop commands or the @samp{finally-return} macro argument.
 
 @lisp
 ;; => (1 2 3)
@@ -3054,7 +3056,8 @@ be overridden by using the the @samp{return} and 
@samp{return-from} loop command
 
 @vindex loopy-result
 Unlike @code{cl-loop}, Loopy uses a default accumulation variable, which is 
named
-@code{loopy-result}.  This variable can be used in the @samp{after-do}, 
@samp{finally-do}, and
+@code{loopy-result}.  When used this way, @code{loopy-result} is described as 
an
+@dfn{implied accumulation variable} or an @dfn{implicit accumulation 
variable}.  This variable can be used in the @samp{after-do}, 
@samp{finally-do}, and
 @samp{finally-return} special macro arguments.
 
 @lisp
@@ -3064,25 +3067,83 @@ Unlike @code{cl-loop}, Loopy uses a default 
accumulation variable, which is name
        (collect i)
        (finally-return (cons 0 loopy-result)))
 
+;; => (0 1 2 3)
+(loopy (list i '(1 2 3))
+       (collect i)
+       (after-do (push 0 loopy-result)))
+
 ;; => (0 1 2 3)
 (loopy (list i '(1 2 3))
        (collect i)
        (finally-do (push 0 loopy-result)))
 @end lisp
 
-In general, you should not attempt to modify or use the value of 
@code{loopy-result}
-during the loop when it is used as the implied accumulation variable for a
-command, as it is not guaranteed to have a correct value when efficiently
-building sequences.  For example, it is often faster to build a list in reverse
-instead of appending to its end.  For some commands, such as those in
-@ref{Numeric Accumulation} and @ref{Generic Accumulation}, this does not 
matter.
+Like in @code{cl-loop}, when multiple accumulation commands do not name an
+accumulation variable, they will all use the same implied accumulation variable
+(@code{loopy-result}).  As a consequence, one must explicitly name separate
+accumulation variables to be able to accumulate into separate values.  This can
+make accumulation slower, because @code{loopy} ensures that named accumulation
+variables (excluding the previously mentioned @code{loopy-result}) have the 
correct
+value during the loop.  For example, @code{loopy} will construct named 
accumulation
+variables containing lists in the correct order, instead of using the more
+efficient @code{push}-@code{nreverse} idiom.  This behavior can be disabled by 
optimizing
+accumulation variables using the @samp{accum-opt} special macro argument
+(@ref{Optimizing Accumulations}).
+
+@lisp
+;; Both command usages of `collect' and `append'
+;; use `loopy-result' as the implied accumulation variable:
+;;
+;; => (1 11 2 12 3 13)
+(loopy (list i '(1 2 3))
+       (collect i)
+       (append (list (+ 10 i)) :at end)
+       (finally-return loopy-result))
+@end lisp
+
+In general, you should not attempt to modify or use the value of optimized
+accumulation variables during the loop, including @code{loopy-result} when it 
is used
+as the implied accumulation variable for a command, because they are not
+guaranteed to have a correct value when efficiently building sequences
+(@ref{Optimizing Accumulations}).  For some commands, such as those listed in 
@ref{Numeric Accumulation}
+and @ref{Generic Accumulation}, this does not matter.
+
+@lisp
+;; See that `loopy-result' is not in the correct order during the loop
+;; (the exact value of an optimized accumulation variable during the loop
+;; is an implementation detail):
+;;
+;; => (6 5 4 3 2 1)
+(loopy (number i :from 1 :to 10)
+       (collect i)
+       (when (> i 5)
+         (return loopy-result)))
+@end lisp
+
+Implied results are only required to be correct after the loop ends (before 
code
+in @samp{else-do} is run).  Furthermore, because using a @samp{return} or 
@samp{return-from}
+command overrides implied return values, using these commands can prevent
+implied accumulation results from being finalized.  Using the @samp{leave} 
command,
+which exits the loop without returning a value, does not affect the correctness
+of implied results.
+
+@lisp
+;; See that the `leave' command does not prevent finalizing
+;; optimized accumulation variables, unlike the above `return' command:
+;;
+;; => (1 2 3 4 5 6)
+(loopy (number i :from 1 :to 10)
+       (collect i)
+       (when (> i 5) (leave)))
+@end lisp
 
 Be aware that explicitly named accumulation variables do not affect the implied
 return value of a loop.  Such values must be returned explicitly, or they will
 be ignored when the macro returns a value.  This limitation is needed for more
 consistently handling the complexity that comes from allowing unknown kinds of
-destructuring via the alternative destructuring systems.  This may change in 
the
-future.
+destructuring via the alternative destructuring systems, such as the possibly
+intermediate variables that can be generated by @code{pcase} patterns.  This 
may
+change in the future.
 
 @lisp
 ;; See how the variable `my-explicit-variable' is ignored when
@@ -3115,14 +3176,12 @@ accumulation results.
 @end lisp
 
 @cindex accumulation compatibility
-Like in @code{cl-loop}, when using implied variables, multiple accumulation 
commands
-will use the same variable (@code{loopy-result}).  For all accumulation 
variables
-used by multiple accumulation commands, you should make sure that the commands
-are actually compatible.  If not, then @code{loopy} will signal an error.
-
-For example, you should not try to accumulate @samp{collect} results and 
@samp{sum}
-results into the same variable, as you cannot use a list as a number.  On the
-other hand, @samp{sum} and @samp{multiply} are compatible, since they both act 
on numbers.
+For all accumulation variables used by multiple accumulation commands, you
+should make sure that the commands are actually compatible.  If not, then
+@code{loopy} will signal an error.  For example, you should not try to 
accumulate
+@samp{collect} results and @samp{sum} results into the same variable, as you 
cannot use a
+list as a number.  On the other hand, @samp{sum} and @samp{multiply} are 
compatible, since
+they both act on numbers.
 
 @lisp
 ;; Incompatible commands:
@@ -3140,12 +3199,13 @@ other hand, @samp{sum} and @samp{multiply} are 
compatible, since they both act o
 @end lisp
 
 @cindex accumulation initial values
-Each accumulation command has a default initialization value for the
-accumulation variable.  For most commands, this is @code{nil}.  This 
documentation
-tries to note when it is not @code{nil}.  For example, the default starting 
value for
-the @samp{sum} command is @code{0} and the default starting value for the 
@samp{multiply}
-command is @code{1}.  The default initialization value used by an accumulation
-command can be overridden using the @samp{with} special macro argument.
+In the same general area as accumulation command compatability, you should keep
+in mind that each accumulation command has a default initialization value for
+the accumulation variable.  For most commands, this is @code{nil}.  This
+documentation tries to note when it is not @code{nil}.  For example, the 
default
+starting value for the @samp{sum} command is @code{0} and the default starting 
value for
+the @samp{multiply} command is @code{1}.  The default initialization value 
used by an
+accumulation command can be overridden using the @samp{with} special macro 
argument.
 
 @quotation Warning
 Currently, a warning is raised when the default initial values of accumulation
@@ -3173,105 +3233,8 @@ conflict, use the @samp{with} special macro argument, 
as noted above.
        (finally-return my-accum))
 @end lisp
 
-One must specify separate accumulation variables to be able to accumulate into
-separate values.  This can make accumulation slower, because @code{loopy} 
ensures
-that named accumulation variables (excluding the previously mentioned
-@code{loopy-result}) have the correct value during the loop.  For example, 
@code{loopy}
-will construct named accumulation variables containing lists in the correct
-order, instead of using the more efficient @code{push}-@code{nreverse} idiom.  
This
-behavior can be disabled by optimizing accumulations using the @samp{accum-opt}
-special macro argument (@ref{Optimizing Accumulations}).
-
-Below are examples of an optimized accumulation and an un-optimized
-accumulation.  See that the example expansion of the un-optimized accumulation
-is more complex and uses a slower way of building the accumulated list.
-
-@lisp
-;; Optimized accumulation:
-;;
-;; => (1 3 2 6 3 9)
-(loopy (accum-opt coll)
-       (numbers i :from 1 :to 3)
-       (collect coll i)
-       (collect coll (* i 3))
-       (finally-return coll))
-
-;; Optimized example expansion:
-;;
-;; => (1 3 2 6 3 9)
-(let* ((coll nil)
-       (i 1)
-       (nums-end192 3)
-       (nums-increment191 1))
-  (cl-block nil
-    (while (<= i nums-end192)
-      (setq coll (cons i coll))
-      (setq coll (cons (* i 3) coll))
-      (setq i (1+ i)))
-    (setq coll (nreverse coll)))
-  coll)
-@end lisp
-
-@lisp
-;; Unoptimized accumulation:
-;;
-;; => (1 3 2 6 3 9)
-(loopy (numbers i :from 1 :to 3)
-       (collect coll i)
-       (collect coll (* i 3))
-       (finally-return coll))
-
-;; Unoptimized example expansion:
-;;
-;; => (1 3 2 6 3 9)
-(let* ((coll nil)
-       (coll-last-link-190 coll)
-       (i 1)
-       (nums-end189 3)
-       (nums-increment188 1))
-  (cl-block nil
-    (while (<= i nums-end189)
-      (cond
-       (coll-last-link-190
-        (setcdr coll-last-link-190 (list i))
-        (setq coll-last-link-190 (cdr coll-last-link-190)))
-       (coll
-        (setq coll-last-link-190 (last coll))
-        (setcdr coll-last-link-190 (list i))
-        (setq coll-last-link-190 (cdr coll-last-link-190)))
-       (t
-        (setq coll (list i)
-              coll-last-link-190 coll)))
-      (cond
-       (coll-last-link-190
-        (setcdr coll-last-link-190 (list (* i 3)))
-        (setq coll-last-link-190 (cdr coll-last-link-190)))
-       (coll
-        (setq coll-last-link-190 (last coll))
-        (setcdr coll-last-link-190 (list (* i 3)))
-        (setq coll-last-link-190 (cdr coll-last-link-190)))
-       (t
-        (setq coll (list (* i 3))
-              coll-last-link-190 coll)))
-      (setq i (1+ i))))
-  coll)
-@end lisp
-
-@quotation Warning
-In general, you should not try to access implied (or optimized) accumulation
-results (for example, @code{loopy-result}) while the loop is running.  Implied
-results are only required to be correct after the loop ends (before code in
-@samp{else-do} is run), allowing for more efficient code.
-
-Furthermore, because using a @samp{return} or @samp{return-from} command 
overrides implied
-return values, using these commands can prevent implied accumulation results
-from being finalized.  Using the @samp{leave} command, which exits the loop 
without
-returning a value, does not affect the correctness of implied results.
-
-@end quotation
-
 @menu
-* Common Properties of Accumulation Commands::
+* Common Properties and Arguments of Accumulation Commands::
 * Generic Accumulation::         Accumulating function output.
 * Numeric Accumulation::         Using and returning numbers.
 * Sequence Accumulation::        Using and returning sequences.
@@ -3279,8 +3242,8 @@ returning a value, does not affect the correctness of 
implied results.
 * Optimizing Accumulations::     Producing efficient accumulations.
 @end menu
 
-@node Common Properties of Accumulation Commands
-@subsection Common Properties of Accumulation Commands
+@node Common Properties and Arguments of Accumulation Commands
+@subsection Common Properties and Arguments of Accumulation Commands
 
 You will notice that each accumulation command has an alias of the command name
 in the present participle form (the ``-ing'' form).  For example, instead of
@@ -5007,7 +4970,7 @@ using the @code{let*} special form.
 This method recognizes all commands and their aliases in the user option
 @code{loopy-parsers}.
 
-@float Listing,orgf6ce5d7
+@float Listing,org0175e90
 @lisp
 ;; => ((-9 -8 -7 -6 -5 -4 -3 -2 -1)
 ;;     (0)
@@ -5408,11 +5371,6 @@ method).
 Flags are applied in order.  If you specify @samp{(flags seq pcase)}, then 
@code{loopy}
 will use @code{pcase-let} for destructuring, not @code{seq-let}.
 
-@vindex loopy-default-flags
-If you wish to always use a flag, you can add that flag to the list
-@code{loopy-default-flags}.  These can be overridden by any flag given in the 
@samp{flag}
-special macro argument.
-
 The following flags are currently supported:
 
 @cindex pcase flag
@@ -5504,45 +5462,6 @@ yet provide the required functionality.
        (finally-return (+ sum1 v1) (+ sum2 v2)))
 @end lisp
 
-If you wish to always use one of the destructuring flags, you can use a 
wrapping
-macro around @code{loopy} or @code{loopy-iter}.  The @samp{flag} special macro 
argument is
-identified by its entry in the customizable variable @code{loopy-parsers}.  
Hence,
-uses of @samp{flag}, including aliases, can be identified by checking 
@code{loopy-parsers}
-(so long as the entry for @samp{flag} itself has not been changed).
-
-@lisp
-(require 'loopy-pcase)
-(defmacro my-loopy-flag-wrapper (&rest body)
-  "Use `loopy', but default to `pcase' destructuring."
-  (loopy (with (flag-found nil))
-         (list arg body)
-         (collect (if (and (consp arg)
-                           (eq (map-elt loopy-parsers (car arg))
-                               (map-elt loopy-parsers 'flag)))
-                      (progn
-                        (setq flag-found t)
-                        (append arg '(pcase)))
-                    arg))
-         (finally-return
-          `(loopy ,@@(unless flag-found
-                      '((flag pcase)))
-                  ,@@loopy-result))))
-
-;; => (1 2 3 4)
-(my-loopy-flag-wrapper (list `(,i . ,j) '((1 . 2) (3 . 4)))
-                       (collect i)
-                       (collect j))
-
-;; Ignores the `seq' flag as expected:
-;;
-;; => ( 1 2 3 4)
-(my-loopy-flag-wrapper (flag seq)
-                       (list `(,i . ,j) '((1 . 2) (3 . 4)))
-                       (collect i)
-                       (collect j))
-@end lisp
-
-
 @quotation Warning
 For accumulation commands, there is no guarantee that a variable that was used
 in destructuring was meant to be user-facing.  Destructuring systems can create
@@ -5551,14 +5470,12 @@ variables.
 
 @end quotation
 
-
 Consider the below example in which a hypothetical @code{pcase} pattern 
creates the
 variable @code{temporary?} for destructuring.  Loopy has no way of knowing 
whether it
 was the user who create the variable, or the destructuring system.  As a 
result,
 @code{temporary?} is treated as an accumulation variable.  Such cases can be 
unwanted
 and produce inefficient code.
 
-
 @lisp
 ;; Possibly unexpected behavior:
 ;;
@@ -5571,6 +5488,44 @@ and produce inefficient code.
        (finally-return whole temporary?))
 @end lisp
 
+If you wish to always use one of the destructuring flags, you can use a 
wrapping
+macro around @code{loopy} or @code{loopy-iter}.  The @samp{flag} special macro 
argument is
+identified by its entry in the customizable variable @code{loopy-parsers}.
+Therefore, uses of @samp{flag}, including aliases, can be identified by 
checking
+@code{loopy-parsers} (so long as the entry for @samp{flag} itself has not been 
changed).
+
+@lisp
+(require 'loopy-pcase)
+(defmacro my-loopy-flag-wrapper (&rest body)
+  "Use `loopy', but default to `pcase' destructuring."
+  (loopy (with (entry-for-flag (map-elt loopy-parsers 'flag)))
+         (list arg body)
+         (if (and (consp arg)
+                  (eq (map-elt loopy-parsers (car arg))
+                      entry-for-flag))
+             (command-do
+              (set flag-found t)
+              (collect (append arg '(pcase))))
+           (collect arg))
+         (finally-do
+          (unless flag-found
+            (push '(flag pcase) loopy-result))
+          (push 'loopy loopy-result))))
+
+;; => (1 2 3 4)
+(my-loopy-flag-wrapper (list `(,i . ,j) '((1 . 2) (3 . 4)))
+                       (collect i)
+                       (collect j))
+
+;; Ignores the `seq' flag as expected:
+;;
+;; => ( 1 2 3 4)
+(my-loopy-flag-wrapper (flag seq)
+                       (list `(,i . ,j) '((1 . 2) (3 . 4)))
+                       (collect i)
+                       (collect j))
+@end lisp
+
 @node Custom Aliases
 @section Custom Aliases
 
@@ -5597,7 +5552,7 @@ between aliases and preferred names (which are the ones 
commonly used and listed
 first in this document).  We continue to use the word ``alias'' for its common
 definition rather than to suggest a difference in the code.
 
-@float Listing,orgc46048a
+@float Listing,org7c76d17
 @lisp
 ;; => ("a" "b" "c" "d")
 (loopy (array i "abcd")
diff --git a/tests/tests.el b/tests/tests.el
index 3ebd54107e5..a85ffbc5c81 100644
--- a/tests/tests.el
+++ b/tests/tests.el
@@ -466,6 +466,26 @@ writing a `seq-do' method for the custom seq."
   :iter-keyword t
   :repeat _after)
 
+(loopy-deftest after-do-modifies-implied-result-var
+  :doc "`after-do' should be able to modify the return value by modifying
+`loopy-result', even when `loopy-result' is used as an impled return value.
+
+This case should not have to be treated differently by the user."
+  :result '(0 1 2 3)
+  :multi-body t
+  :body [((list i '(1 2 3))
+          (collect i)
+          (after-do (push 0 loopy-result)))
+
+         ((list i '(1 2 3))
+          (collect loopy-result i)
+          (after-do (push 0 loopy-result))
+          (finally-return loopy-result))]
+  :loopy t
+  :iter-keyword (list collect)
+  :iter-bare ((list . listing)
+              (collect . collecting)))
+
 ;;;; Before and After
 (loopy-deftest basic-before-and-after-test
   :result 3


Reply via email to