|(require control)||package: control|
- added documentation in Scribble form
- added begin/goto
(while test body)
Semantics: while is an iteration construct. Each iteration begins by evaluating the test expression. If it evaluates to a true value, the body expressions are evaluated sequentially from left to right, then the next iteration begins. If the test expression evaluates to false then iteration stops and an unspecified value is returned as the result of the while-expression.
(until test body)
Semantics: until is an iteration construct. Each iteration begins by evaluating the body expressions sequentially from left to right. The test expression is then evaluated. If the result is a true value, then the next iteration begins. Otherwise the iteration stops and unspecified value is returned as the result of the until-expression.
(dotimes (variable expression [finally]) body)
Semantics: dotimes is an iteration contructs. Evalutations begins by evaluating expression. If the result is not an integer an error is signaled. If the result is zero or negative, the body expressions are not evaluated. Otherwise the body expressions are evaluated for each integer from 0 up to but not including the result of expression.
During each evaluation of the body expressions, variable is bound to each integer.
When the iteration stops finally is evaluated if present and the result returned, otherwise void is returned. During evaluation of finally the variable is bound to the number of times the body were evaluated.
(tagged-begin (tag / expression)*)
Motivation: The macro tagged-begin is inspired by the Common Lisp construct tagbody.
Semantics: The tagged-begin expression evaluates the expressions in a lexical environment, where go and return are are bound to functions of one argument, which will transfer control when called.
As main rule the expressions will be evaluated sequentially from left to right. When there are no more expressions to be evaluated void is returned.
If an expression evaluates (go tag then control is transfered to the expression following the tag. The tags have lexical scope. The dynamic extent of tag is indefinite. An (go tag) is allowed to tranfer control to an outer tagged-begin. The call (go tag) has the proper tail recursive property, even in situation where the call syntactically is not in tail position.
If (return expression) is evaluted, the value of expression is returned as the value of the entire tagged-begin form.
> (require control)
> (let ([i 0]) (tagged-begin loop (set! i (+ i 1)) (when (< i 41) (go loop))) i)
> (let ([odd-numbers '()] [a 0]) (tagged-begin start (set! a 0) on-odd (set! a (+ a 1)) (set! odd-numbers (cons a odd-numbers)) (cond [(>= a 9) (go end)] [(even? a) (go on-even)] [else (go on-odd)]) on-even (set! a (+ a 1)) (go on-odd) end) odd-numbers)
'(10 8 6 4 2 1)
References: "Applications of Continuations" of Daniel P. Friedman.
Motivation: Think of begin/goto as a normal begin, where can be used to jump to a control point named by a label. An ( identifier) will transfer control to the point named by the identifier. If the goto-form is one of the label-or-goto-expression, then a goto doesn’t grow the control context.
> (require control)
> (let ([x 1]) (let/ec return (begin/goto ( l1) (set! x (+ x 1)) (when (= x 10000000) (return x)) ( l1))))
> (let ([x 1]) (let/ec return (begin/goto ( l1) (set! x (+ x 1)) (when (= x 10000000) (return x)) ( l1) 2)))