Skip to content

Commit

Permalink
Warn that always, never, and thereis should not use multiple co…
Browse files Browse the repository at this point in the history
…nditions.

These commands will be changed to have function signatures more like
accumulation commands, with an optional initial `VAR` argument.

- Update the commands to `warn`.
- Update the Org document and Texinfo file.

This is tracked in #145.
  • Loading branch information
okamsn committed Aug 12, 2023
1 parent f4f389f commit acd9c2d
Show file tree
Hide file tree
Showing 5 changed files with 309 additions and 125 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ This document describes the user-facing changes to Loopy.
(list i '(4 5 6)))
```

- 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.

### Command Improvements

- To produce faster code, some commands now avoid creating an intermediate
Expand Down
5 changes: 5 additions & 0 deletions README.org
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ please let me know.
/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.
- Versions 0.11.1 and 0.11.2: None. Bug fixes.
- Version 0.11.0:
- More incorrect destructured bindings now correctly signal an error.
Expand Down
62 changes: 21 additions & 41 deletions doc/loopy-doc.org
Original file line number Diff line number Diff line change
Expand Up @@ -3083,18 +3083,18 @@ value (both using ~loopy-result~).
#+end_quote

#+findex: always
- =(always EXPR [EXPRS] &key into)= :: Check the result of each condition
=EXPR=. If any condition evaluates to ~nil~, end the loop. Otherwise, the
loop returns the final value of conditions or ~t~ if the command is never run.
- =(always EXPR &key into)= :: Check the result of the condition =EXPR=. If the
condition evaluates to ~nil~, end the loop. Otherwise, the loop returns the
final value of the condition or ~t~ if the command is never run.

The steps are thus:
1. The variable (by default, ~loopy-result~) is initially bound to ~t~, using
it as the implicit return value of the loop.
2. When the conditions are checked, the variable is bound to the value of
the ~and~-ed conditions.
2. When the condition is checked, the variable is bound to the value of
the condition.
3. If the variable is ~nil~, the loop is exited.
4. If the loop completes successfully, then the variable is the final value
of the conditions. If the command is never run, then the variable will
of the condition. If the command is never run, then the variable will
remain ~t~.


Expand All @@ -3103,43 +3103,36 @@ value (both using ~loopy-result~).
(loopy (list i '(1 0 1 0 1))
(always (< i 2)))

;; => nil
;; Returns the final value of the condition:
;; => 5
(loopy (list i '(1 0 1 0 1))
(always (< i 1)))
(always (and (< i 2) 5)))

;; => t
;; => nil
(loopy (list i '(1 0 1 0 1))
;; Note: can accept multiple conditions.
;; This is equivalent to `(always (and (< i 2) (>= i 0)))'.
(always (< i 2) (>= i 0)))

;; => "hello there"
(loopy (list i '(1 1 1 1))
;; The return value of `(and (< i 2) "hello")' is "hello".
(always (< i 2) "hello")
(finally-return (concat loopy-result " there")))
(always (< i 1)))

;; NOTE: Here, the implicit return value is `t' because an
;; `always' command was used, and that return value
;; is never updated to "hello" because the `always'
;; command is never actually used.
;; command is never actually run.
;;
;; => t
(loopy (list i '(1 1 1 1))
(when nil
(always (> i 5) "hello")))
(always (and (> i 5) "hello"))))
#+END_SRC

#+findex: never
- =(never EXPR [EXPRS] &key into)= :: Check each condition =EXPR=. If any
condition is ever non-nil, then the loop is exited and returns ~nil~.
Otherwise the loop returns ~t~.
- =(never EXPR &key into)= :: Check the condition =EXPR=. If the condition is
ever non-nil, then the loop is exited and returns ~nil~. Otherwise the loop
returns ~t~.

The steps are thus:
1. The variable (by default, ~loopy-result~) is initialized to ~t~ and used as
the loop's implicit return value.
2. The values of the condition are checked.
3. If any of the conditions are non-nil, then the variable is set to ~nil~
2. The value of the condition is checked.
3. If the condition is non-nil, then the variable is set to ~nil~
and the loop is ended via the =leave= command.


Expand All @@ -3163,14 +3156,6 @@ value (both using ~loopy-result~).
(loopy (list i '(1 0 1 0 1))
(never (= i 0)))

;; Like `always', `never' can also accept multiple arguments. They are
;; treated as `(never (or COND1 COND2 ... CONDN))'.

;; => t
(loopy (list i '(1 0 1 0 1))
;; equivalent to `(never (or (= i 3) (= i 4)))'.
(never (= i 3) (= i 4)))

;; This example taken from the documentation of CL's Iterate package.
;;
;; => 2, not t
Expand All @@ -3180,14 +3165,14 @@ value (both using ~loopy-result~).
#+end_src

#+findex: thereis
- =(thereis EXPR [EXPRS] &key into)= :: Check the result of each condition
=EXPR=. If all conditions evaluate to a non-~nil~ value, the loop returns
- =(thereis EXPR &key into)= :: Check the result of the condition
=EXPR=. If the condition evaluates to a non-~nil~ value, the loop returns
that value. Otherwise, the loop returns nil.

The steps are thus:
1. The variable (by default, ~loopy-result~) is initialized to ~nil~ and used
as the implicit return value of the loop.
2. The value of the conditions are stored in the variable.
2. The value of the condition is stored in the variable.
3. If the value of the variable is non-nil, the loop exits.


Expand All @@ -3201,11 +3186,6 @@ value (both using ~loopy-result~).
(loopy (list i '(1 0 1 0 1))
(thereis (and (> i 2) i)))

;; => nil
(loopy (list i '(1 0 1 0 1))
;; Same as above. Like `always' uses an explicit `and'.
(thereis (> i 2) i))

;; => 7
(loopy (list i '(nil nil 3 nil))
(thereis i)
Expand Down
Loading

0 comments on commit acd9c2d

Please sign in to comment.