Intermediate loops

goof.scm
  * Changed cl-next to properly push all intermediate loops
  * Changed emit-many/rest to emit intermediate loops
  * Added loop/list as a shorthand for just accumulating lists.

tests.scm
  * Collected some things I wanted ta have to track regressions.

README.md
  * Reflect above changes
This commit is contained in:
Linus 2020-11-04 23:15:32 +01:00
parent f2496604d5
commit be9ac1a55d
3 changed files with 108 additions and 54 deletions

View file

@ -26,7 +26,19 @@ Compared to foof-loop, some things are added. Apart from minor syntactic changes
=> acc)
```
This will sum all the sublists of lst and produce the result 21. Any :when, :unless, or :break clause will break out a subloop if any subsequent for clauses are found.
This will sum all the sublists of lst and produce the result 21. Any :when, :unless, :break, or :subloop clause will break out a subloop if any subsequent for clauses are found.
Accumulators can be in any of the loop's stages:
```
(loop ((:for a (in-list '(1 2 3)))
(:acc aa (summing a))
:subloop
(:for b (up-from a (to (+ a 2))))
(:acc ab (listing b)))
=> (values aa ab))
;; => (values 6 (1 2 2 3 3 4))
```
## Differences from foof-loop
@ -42,11 +54,13 @@ with-clauses are removed in favour of (:for var (in init [step [stop]]))
accumulators are no longer for-clauses, but should be prepended with :acc.
### Regressions
### Regressions compared to foof-loop
only :acc clauses are visible in the final-expression. This is due to for-clauses not being promoted through to outer loops (since they should not keep their state).
:for clauses cannot finalize, due to the above thing. The reason for distinguishing between :for and :acc is to be able to promote accumulators outwards and finalizers inwards. This is not implemented.
:for clauses cannot finalize, due to the above thing. The reason for distinguishing between :for and :acc is to be able to promote accumulators outwards and finalizers inwards. This is not implemented yet, however.
Due to clause reordering, positional updates are not supported. If you want to update your loop vars, do so using named update (see below).
### changes
@ -54,8 +68,6 @@ only :acc clauses are visible in the final-expression. This is due to for-clause
(with var 10 (- var 1) negative?) => (:for var (in 10 (- var 10) (negative? var)))
Positional updates of variables is not supported, due to goof-loop reordering the loop-vars - which there are reasons for.
### similarities
You can of course still have a larger control of your loops:
@ -90,11 +102,6 @@ Named updates also work.
## Todo
Currently, there is a bug if you have subloops more than 2 loops deep where all accumulators are reset. This should be an easy fix.
Regarding the above: fixing that bug does nothing! I can only output loops of at most 2.
Should we add finalizers for :for-clauses? I can't see the need outside of a potential (in-file ...), which can't be properly supported anyway since I won't do any dynamic-wind stuff.
Is (:for var (in init step stop)) and (:acc var (in init update)) good syntax? the :with clause of foof-loop is nice, but what should it be called for accumulators? Should we go back to calling both :acc and :for just ":for" and re-add :with and an accumulating counterpart? What should that accumulating counterpart be called? :acc?