Updated documentation to reflect previous change.

This commit is contained in:
Linus 2021-03-18 12:43:56 +01:00
parent 5847bd21d4
commit 78aed79463
2 changed files with 19 additions and 3 deletions

View file

@ -29,6 +29,8 @@
loop-clause = (:for id id* ... seq-expr)
| (:acc id id* ... seq-expr)
| (:let id expr)
| (:let* id expr)
| (:when guard-expr)
| (:unless guard-expr)
| (:break break-expr)
@ -103,13 +105,17 @@
</dd></dt><dt><a id="loop/and"><b>Scheme syntax: </b>loop/and</a><dd><code>(loop/and (clauses ...) body ...)</code><br /><p>If all evaluated bodies return truthy, return the result of the last evaluated body. If any body returns #f, stop iteration and return #f. If no body is evaluated, #t is returned.</p>
</dd></dt><dt><a id="loop/or"><b>Scheme syntax: </b>loop/or</a><dd><code>(loop/or (clauses ...) body ...)</code><br /><p>If any evaluated body returns truthy, stop iteration and return the result of that body. If no body returns truthy, return #f. If no body is evaluated, return #f.</p>
</dd></dt><dt><a id="loop/list/parallel"><b>Scheme syntax: </b>loop/list/parallel</a><dd><code>(loop/list/parallel (clauses ...) body ...)</code><br /><p>Like loop/list, but evaluates each body in parallel.</p>
</dd></dt></dl></div><div id=":for-clauses"><h3>:for-clauses</h3><dl><dt><a id="in"><b>Scheme syntax: </b>in</a><dd><code>(:for binding (in start [update [stop]]))</code><br /><p>Binds a loop variable to <code>binding</code>. Its first value is <code>start</code>. It is updated by the <code>update</code> expression, or is left unchanged if no such expression is present. If a <code>stop</code> expression is provided, it will be evaluated before each loop body. If the <code>stop</code> expression returns true, the iteration will be considered exhausted.</p>
</dd></dt></dl></div><div id=":for-clauses"><h3>:for-clauses</h3><p>A :for clause specifies a number of identifiers that are bound to a value from a sequence. <code>(:for i (up-from 0 10)))</code> will bind a to all integers between 0 and 10 (excluseve) in order. The first time the loop is executed, it is bound to 0, then 1, then 2, and so on. Some loops has support for exposing their loop variables to the user. In the case of <code>(:for elt pair (in-list lst))</code>, <code>elt</code> will be bound to the car of <code>pair</code>, whereas <code>pair</code> will be bound to the loop variable used by <code>in-list</code> to hold the current position of the list.</p>
<dl><dt><a id="in"><b>Scheme syntax: </b>in</a><dd><code>(:for binding (in start [update [stop]]))</code><br /><p>Binds a loop variable to <code>binding</code>. Its first value is <code>start</code>. It is updated by the <code>update</code> expression, or is left unchanged if no such expression is present. If a <code>stop</code> expression is provided, it will be evaluated before each loop body. If the <code>stop</code> expression returns true, the iteration will be considered exhausted.</p>
<pre class="code-example">
(loop ((:for a (in 0 b)) (:for b (in 1 (+ a b) (&gt; b 20))))
(display b) (newline))
</pre><p>Will print all fibonacci numbers below 20.</p>
</dd></dt><dt><a id="up-from"><b>Scheme syntax: </b>up-from</a><dd><code>(:for binding (up-from start [(to bound)] [(by step)]))</code><br /><code>(:for binding (up-from start [bound [by]]))</code><br /><p>Binds <code>binding</code> to the number <code>start</code> up to <code>bound</code> (exclusive!) by <code>step</code>. If no <code>bound</code> is given, it will yield values indefinitely. The second shorter form will not allow unbounded iteration if a <code>step</code> other than <code>1</code> is wanted.</p>
<p><code>binding</code> is a loop variable and can thus be changed using named updates.</p>
</dd></dt><dt><a id="up-from"><b>Scheme syntax: </b>up-from</a><dd><code>(:for binding (up-from start [(:to bound)] [(:by step)]))</code><br /><code>(:for binding (up-from start [bound [by]]))</code><br /><p>Binds <code>binding</code> to the number <code>start</code> up to <code>bound</code> (exclusive!) by <code>step</code>. If no <code>bound</code> is given, it will yield values indefinitely. The second shorter form will not allow unbounded iteration if a <code>step</code> other than <code>1</code> is wanted.</p>
<p><code>binding</code> is a loop variable and can thus be changed using named updates.</p>
</dd></dt><dt><a id="down-from"><b>Scheme syntax: </b>down-from</a><dd><code>(:for binding (down-from start [(to bound)] [(by step)])</code><br /><code>(:for binding (down-from start [bound [by]]))</code><br /><p>Binds <code>binding</code> to the number <code>(- start 1)</code> down to <code>bound</code> (inclusive!) by <code>step</code>. If no <code>bound</code> is given, it will yield values indefinitely. The second shorter form will not allow unbounded iteration if a <code>step</code> other than <code>1</code> is wanted.</p>
<p><code>binding</code> is a loop variable and can thus be changed using named updates.</p>
</dd></dt><dt><a id="in-list"><b>Scheme syntax: </b>in-list</a><dd><code>(:for binding [pair] (in-list expr [by])</code><br /><p>Binds <code>binding</code> to the car of the loop variable <code>pair</code>. <code>pair</code> is advanced by applying the procedure <code>by</code> to it (defaulting to <code>cdr</code>). The iteration stops when <code>pair</code> is the empty list.</p>
</dd></dt><dt><a id="in-lists"><b>Scheme syntax: </b>in-lists</a><dd><code>(:for binding [pairs] (in-lists expr [by])</code><br /><p>Works the same as <code>in-list</code>, but <code>expr</code> must evaluate to a list of lists. <code>binding</code> is bound to the car of those lists, and they are advanced by <code>by</code>, defaulting to <code>cdr</code>.</p>
</dd></dt><dt><a id="in-vector"><b>Scheme syntax: </b>in-vector</a><dd><code>(:for binding [index] (in-vector expr [low [high]]))</code><br /><p>Binds <code>binding</code> to all elements in the vector produced by <code>expr</code> in order from <code>low</code> to <code>high</code>. <code>low</code> defaults to 0 and <code>high</code> defaults to the last index of the vector.</p>

View file

@ -4,6 +4,7 @@
<title>Goof-loop</title>
<author email="linus.internet@fastmail.se">Linus Björnstam</author>
</metadata>
<section title="Preface">
We have all had the thought. *Why oh why are not all our problems solved by a nice recursive algorithm over a list?*. We see a neat problem. We smile and think about all the nice things we shall do right after finishing off this little tidbit, this delicious little bite of a problem. Then we scrape the surface. Under there is a jungle of state. Suddenly our little recursive list-mangling is not enough. To defeat the anxiety rising within us, we quickly write something using map, filter, zip and reduce. We test it. We smile again. We test it on real world data. The smile stiffens. The little bite has turned in to an o(n²) turd.
@ -53,6 +54,8 @@
loop-clause = (:for id id* ... seq-expr)
| (:acc id id* ... seq-expr)
| (:let id expr)
| (:let* id expr)
| (:when guard-expr)
| (:unless guard-expr)
| (:break break-expr)
@ -206,6 +209,7 @@
<subsection title=":for-clauses">
A :for clause specifies a number of identifiers that are bound to a value from a sequence. `(:for i (up-from 0 10)))` will bind a to all integers between 0 and 10 (excluseve) in order. The first time the loop is executed, it is bound to 0, then 1, then 2, and so on. Some loops has support for exposing their loop variables to the user. In the case of `(:for elt pair (in-list lst))`, `elt` will be bound to the car of `pair`, whereas `pair` will be bound to the loop variable used by `in-list` to hold the current position of the list.
<spec>
<syntax name="in">
@ -218,13 +222,17 @@
</example>
Will print all fibonacci numbers below 20.
`binding` is a loop variable and can thus be changed using named updates.
</syntax>
<syntax name="up-from">
<form>(:for binding (up-from start [(to bound)] [(by step)]))</form>
<form>(:for binding (up-from start [(:to bound)] [(:by step)]))</form>
<form>(:for binding (up-from start [bound [by]]))</form>
Binds `binding` to the number `start` up to `bound` (exclusive!) by `step`. If no `bound` is given, it will yield values indefinitely. The second shorter form will not allow unbounded iteration if a `step` other than `1` is wanted.
`binding` is a loop variable and can thus be changed using named updates.
</syntax>
<syntax name="down-from">
@ -232,6 +240,8 @@
<form>(:for binding (down-from start [bound [by]]))</form>
Binds `binding` to the number `(- start 1)` down to `bound` (inclusive!) by `step`. If no `bound` is given, it will yield values indefinitely. The second shorter form will not allow unbounded iteration if a `step` other than `1` is wanted.
`binding` is a loop variable and can thus be changed using named updates.
</syntax>
<syntax name="in-list">