Skip to content

Commit

Permalink
Clean up documentation files.
Browse files Browse the repository at this point in the history
- Remove old changes from the list of recent changes in the README.
- Add missing PR and Issue numbers to the change log.
- Clean up examples.
- In the README, stop saying that we are "experimenting" with `loopy-iter`.
  It was added over a year ago.
- Briefly describe the default destructuring system in the README.
- Clean up examples.
- Mention place-wise optimization of accumulations in the Introduction of the
  Org doc.
- Add examples for working around implementation details of `iter` command.
- Add that it is an error to re-use iteration variables.
- Add the paragraph of initial accumulation values to the concept index.
- Fix `adjoin` example now that `equal` is the default test.
- Remove `key` examples for now, since we know `key` is wrong.
  Will add back after fixing.  Also remove from command signatures.
- List `at` in `vconcat`'s command signature.
- Remove `result-type` example from `collect`, now that deprecated.
- Mention how `find` works when the loop is left early.
- Remove an implicit description of the `split` flag, which is deprecated.
- Correct a use of "iteration" vars to "other" vars in an example.
- Refer to the library as "Loopy", not "=loopy=", which we use for the
  sub-loop command.
- Use `if-let` and a generated variable in the "Hello World" example.
  • Loading branch information
okamsn committed Oct 8, 2023
1 parent 1a0e7c4 commit 8f4b127
Show file tree
Hide file tree
Showing 3 changed files with 768 additions and 610 deletions.
76 changes: 45 additions & 31 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ This document describes the user-facing changes to Loopy.
### Bugs Fixed

- Rewrite `prepend` in terms of `append`. Rewrite `push-into` in terms of
`collect`. This change makes these commands work with the new system for
`collect` ([#160]). This change makes these commands work with the new system for
optimized accumulation variables.

- Without an explicit starting value for the accumulation variable, `reduce` now
Expand All @@ -22,8 +22,8 @@ This document describes the user-facing changes to Loopy.
(reduce i #'*))
```

- Fix `find` when `:on-failure` is nil. Previously, `nil` was interpreted as
not passing `:on-failure`.
- Fix `find` when `:on-failure` is nil ([#170]). Previously, `nil` was
interpreted as not passing `:on-failure`.

```emacs-lisp
;; Previously erroneously returned 27:
Expand All @@ -34,10 +34,10 @@ This document describes the user-facing changes to Loopy.
(finally-return val))
```

- Fix `find` when `EXPR` is nil and `:on-failure` is given. Previously, after
the test passed and `VAR` was set to `nil`, that `nil` was interpreted as not
passing the test, so that `VAR` then bound to the value passed for
`:on-failure`.
- Fix `find` when `EXPR` is nil and `:on-failure` is given ([#170]).
Previously, after the test passed and `VAR` was set to `nil`, that `nil` was
interpreted as not passing the test, so that `VAR` then bound to the value
passed for `:on-failure`.

```emacs-lisp
;; Previously erroneously returned 27:
Expand Down Expand Up @@ -66,9 +66,12 @@ This document describes the user-facing changes to Loopy.

### Breaking Changes

- Fix how the first accumulated value is used in `reduce`. See [#164] and the
item above.

- Make it an error to re-use iteration variables with multiple iteration
commands. The resulting code shouldn't have worked anyway, but we now report
it as an error during macro expansion.
commands ([#142], [#144]). The resulting code shouldn't have worked anyway,
but we now report it as an error during macro expansion.

```elisp
;; Will now signal an error during expansion:
Expand All @@ -95,17 +98,17 @@ This document describes the user-facing changes to Loopy.

#### Deprecations

- Using multiple conditions in `always`, `never`, and `thereis` is deprecated.
These commands will be changed to have call argument lists more like
accumulation commands, such as `(always [VAR] VAL &key into)`. This will
simplify the code and remove an inconsistency between them and the other
- Using multiple conditions in `always`, `never`, and `thereis` is deprecated
([#145], [#161]). These commands will be changed to have call argument lists
more like accumulation commands, such as `(always [VAR] VAL &key into)`. This
will simplify the code and remove an inconsistency between them and the other
commands.

- `:result-type` is deprecated. This feature was taken from Common Lisp's
Iterate. While useful, this can be done more directly using named
accumulation variables (such as `loopy-result`) in special macro arguments,
such as `finally-return`. Because of `accum-opt`, using named variables is
more flexible.
- `:result-type` is deprecated ([#154], [#162]). This feature was taken from
Common Lisp's Iterate. While useful, this can be done more directly using
named accumulation variables (such as `loopy-result`) in special macro
arguments, such as `finally-return`. Because of `accum-opt`, using named
variables is more flexible.

```elisp
;; Can't be done using only `:result-type'.
Expand All @@ -118,10 +121,10 @@ This document describes the user-facing changes to Loopy.
(cl-coerce triples 'vector)))
```

- `:init` is deprecated. Some commands had special behavior with `:init`, such
as `set-prev`, but this has been changed to work with `with` too. Some
iteration commands, such as `numbers`, change behavior based on whether
a variable is `with` bound. Removing `:init` increases consistency
- `:init` is deprecated ([#146], [#163]). Some commands had special behavior with
`:init`, such as `set-prev`, but this has been changed to work with `with`
too. Some iteration commands, such as `numbers`, change behavior based on
whether a variable is `with` bound. Removing `:init` increases consistency
with these commands and decreases the duplication of features.
- Relatedly, remove documentation that said `adjoin` supported `:init`. It
does not.
Expand All @@ -136,17 +139,17 @@ This document describes the user-facing changes to Loopy.
### Command Improvements

- To produce faster code, some commands now avoid creating an intermediate
variable by initializing iteration variables to their first value. This
initialization can be controlled using the `with` special macro argument,
which can result in slower code. Previously, these iteration variables were
always initialized to `nil` and updated to the first value at the location of
the command.
variable by initializing iteration variables to their first value ([#142],
[#144]). This initialization can be controlled using the `with` special macro
argument, which can result in slower code. Previously, these iteration
variables were always initialized to `nil` and updated to the first value at
the location of the command.
- `cycle` already has this behavior, but can now be slower.
- `cons` will initialize to the list value.
- `nums` and `seq-index` will initialize to the first numeric value.

- The behavior of `always`, `never`, and `thereis` has been slightly changed to
be more convenient and consistent with other commands.
be more convenient and consistent with other commands ([#144]).
- The commands now exit the loop without forcing a return value, which allows
implicit return values to be finalized.
- The commands now use variables to store the implicit return values of the
Expand All @@ -166,6 +169,7 @@ This document describes the user-facing changes to Loopy.
```
- As with other incompatible commands, an error is now signaled when trying to
use `thereis` with `always` or `never` **when using the same variable**
([#144]).

- Add a `:test` keyword argument to `numbers` ([#172]). This is useful when the
direction of the iteration is not known ahead of time.
Expand All @@ -182,11 +186,21 @@ This document describes the user-facing changes to Loopy.
### Other Changes

- Add `loopy--other-vars`, given the more explicit restriction on
`loopy--iteration-vars`. For example, these are the variables bound by the
`set` command, which are allowed to occur in more than one command.

`loopy--iteration-vars` ([#144]). For example, these are the variables bound
by the `set` command, which are allowed to occur in more than one command.

[#144]: https://github.com/okamsn/loopy/issue/142
[#144]: https://github.com/okamsn/loopy/pull/144
[#145]: https://github.com/okamsn/loopy/issue/145
[#146]: https://github.com/okamsn/loopy/issue/146
[#154]: https://github.com/okamsn/loopy/issue/154
[#160]: https://github.com/okamsn/loopy/pull/160
[#161]: https://github.com/okamsn/loopy/pull/161
[#162]: https://github.com/okamsn/loopy/pull/162
[#163]: https://github.com/okamsn/loopy/pull/163
[#164]: https://github.com/okamsn/loopy/pull/164
[#165]: https://github.com/okamsn/loopy/pull/165
[#170]: https://github.com/okamsn/loopy/pull/170
[#171]: https://github.com/okamsn/loopy/pull/172
[#173]: https://github.com/okamsn/loopy/pull/173

Expand Down
74 changes: 35 additions & 39 deletions README.org
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,17 @@ please let me know.
- Unreleased:
- The boolean commands =always=, =never=, and =thereis= now behave more like
accumulation commands and use ~loopy-result~ by default.
- Re-using iteration variables in multiple iteration commands now signals
an error.
- By default, the commands =cons=, =iter=, =nums=, and =seq-index=
/can/ update named iteration variables outside of the main loop body
and initialize variables to non-nil values, producing faster code.
This can be overridden via the special macro argument =with=.
- Using multiple conditions in =always=, =never=, and =thereis= is
deprecated. These commands will be changed to have call argument lists
more like accumulation commands, such as =(always [VAR] VAL &key into)=.
This will simplify the code and remove an inconsistency between them and
the other commands.
- Re-using iteration variables in multiple iteration commands now signals
an error. It never produced correct code.
- By default, the commands =cons=, =iter=, =nums=, and =seq-index=
/can/ update named iteration variables outside of the main loop body
and initialize variables to non-nil values, producing faster code.
This can be overridden via the special macro argument =with=.
- =:result-type= is deprecated. Instead, use coercion functions in
special macro arguments, possibly with =accum-opt=.
- The =:init= keyword argument is deprecated. Use the special macro argument
Expand All @@ -58,27 +58,6 @@ please let me know.
flexible and explicit than the non-keyword arguments.
- Fixed a problem with macro expansion in some cases for sub-macros
that created a new macro environment (e.g., ~cl-flet~).
- Versions 0.11.1 and 0.11.2: None. Bug fixes.
- Version 0.11.0:
- More incorrect destructured bindings now correctly signal an error.
- Removed the variable ~loopy-first-iteration~. This can be replaced by just
explicitly using the command =set=.
- ~loopy-iter~ now works differently. See the changelog, manual, and
okamsn/loopy#119 for more info.
- The flag =lax-naming= is deprecated. Its behavior is now the default for
command aliases listed in ~loopy-iter-bare-commands~.
- The user option ~loopy-ignored-names~ is now deprecated. Instead of an
exclusive approach, it is replaced by an inclusive approach using the new
user options ~loopy-iter-bare-commands~ and
~loopy-iter-bare-special-marco-arguments~.
- The command =sub-loop= is deprecated. Use the commands =loopy= and
=loopy-iter= instead.
- The =split= flag is deprecated. Use the more general and controllable
special macro argument =accum-opt= instead.
- ~loopy--accumulation-final-updates~ has been renamed to
~loopy--vars-final-updates~. The old name is now an obsolete alias.
- Removed obsolete aliases for the variables ~loopy-aliases~ and
~loopy-command-parsers~.
- See the [[https://github.com/okamsn/loopy/blob/master/CHANGELOG.md][change log]] for less recent changes.

# This auto-generated by toc-org.
Expand All @@ -95,7 +74,7 @@ please let me know.
* Introduction

The ~loopy~ macro is used to generate code for a loop, similar to ~cl-loop~.
Unlike ~cl-loop~, ~loopy~ uses symbolic expressions instead of "clauses".
Unlike ~cl-loop~, ~loopy~ uses parenthetical expressions instead of "clauses".

#+begin_src emacs-lisp
;; A simple usage of `cl-loop':
Expand All @@ -111,6 +90,12 @@ Unlike ~cl-loop~, ~loopy~ uses symbolic expressions instead of "clauses".
(collect evens i)
(collect odds i))
(finally-return odds evens))

(loopy (numbers i :from 1 :to 10)
(if (cl-evenp i)
(collect i :into evens)
(collect i :into odds))
(finally-return odds evens))
#+end_src

~loopy~ supports destructuring for iteration commands like =list= and
Expand Down Expand Up @@ -142,7 +127,7 @@ accumulation commands like =sum= or =collect=.
#+end_src

The ~loopy~ macro is configurable and extensible. In addition to writing one's
own "loop commands" (such as =list= in the example below), by using "flags", one
own "loop commands" (such as =list= in the example above), by using "flags", one
can choose whether to instead use ~pcase-let~, ~seq-let~, or even the Dash
library for destructuring.

Expand Down Expand Up @@ -171,7 +156,7 @@ Variables like =cars=, =cdrs=, and =digits= in the example above are
automatically ~let~-bound so as to not affect code outside of the loop.

~loopy~ has arguments for binding (or not binding) variables, executing code
before/after the loop, executing code only if the loop completes, and for
before or after the loop, executing code only if the loop completes, and for
setting the macro's return value (default ~nil~). This is in addition to the
looping features themselves.

Expand All @@ -180,38 +165,44 @@ iteration.

* Similar Libraries

Loopy is not the only Lisp library that uses expressions instead of keyword
clauses (like in ~cl-loop~). [[https://common-lisp.net/project/iterate/][Iterate]] and [[https://github.com/Shinmera/for/][For]] are two examples from Common Lisp.
Loopy is not the only Lisp library that uses parenthetical expressions instead of
keyword clauses (like in ~cl-loop~). [[https://common-lisp.net/project/iterate/][Iterate]] and [[https://github.com/Shinmera/for/][For]] are two examples from
Common Lisp.

#+begin_src emacs-lisp
;; Collecting 10 random numbers:
;; cl-loop, iterate, for, loopy

;; cl-loop (Emacs Lisp)
(cl-loop repeat 10 collect (random 10))

;; loopy (Loopy)
(loopy (repeat 10) (collect (random 10)))

;; iterate (Common Lisp)
(iterate (repeat 10) (collect (random 10)))

;; for (Common Lisp)
(for:for ((i repeat 10) (randoms collecting (random 10))))

(loopy (repeat 10) (collect (random 10)))
#+end_src

Generally, all of the packages handle basic use cases in similar ways. One
large difference is that ~iterate~ can embed its looping constructs in arbitrary
code. Loopy is currently experimenting with this feature using a separate
macro, ~loopy-iter~, which expands looping constructs using ~macroexpand~.
code. Loopy is currently provides this feature as a separate macro,
~loopy-iter~, which expands looping constructs using ~macroexpand~.

#+begin_src emacs-lisp
(require 'loopy-iter)

;; Things to node:
;; - `accum-opt' produces more efficient accumulations
;; - `accum-opt' produces more efficient accumulations for names variables
;; - `cycling' is another name for `repeat'
;; => ((-9 -8 -7 -6 -5 -4 -3 -2 -1)
;; (0)
;; (1 2 3 4 5 6 7 8 9 10 11))
(loopy-iter (accum-opt positives negatives zeroes)
(numbering i :from -10 :to 10)
;; Normal `let' and `pcase', not Loopy constructs:
(let ((var (1+ i)))
(pcase var
((pred cl-plusp) (collecting positives var))
Expand Down Expand Up @@ -257,6 +248,9 @@ Commands in Arbitrary Code]]), use

* Multiple Kinds of Destructuring

The default destructuring system is a super-set of what =cl-lib= provides
and is described in the section [[https://github.com/okamsn/loopy/blob/master/doc/loopy-doc.org#basic-destructuring][Basic Destructuring]] in the documentation.

~loopy~ can optionally use destructuring provided by ~pcase-let~, ~seq-let~, the
=dash= library, as well as its own kind. This provides greater flexibility and
allows you to use destructuring patterns that you're already familiar with.
Expand Down Expand Up @@ -301,11 +295,13 @@ accumulation commands.
#+end_src

For more on how =dash= does destructuring, see their documentation on the [[https://github.com/magnars/dash.el#-let-varlist-rest-body][-let]]
form.
expression.

* Loop Commands in Arbitrary Code

The macro ~loopy-iter~ can be used to embed loop commands in arbitrary code.
The macro ~loopy-iter~ can be used to embed loop commands in arbitrary code. It
is similar in use to Common Lisp's Iterate macro, but it is not a port of
Iterate to Emacs Lisp.

#+begin_src emacs-lisp
(require 'loopy-iter)
Expand Down
Loading

0 comments on commit 8f4b127

Please sign in to comment.