💾 Archived View for vierkantor.com › xukut › manual › swail › continuation.gmi captured on 2024-07-08 at 23:34:08. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2024-05-10)
-=-=-=-=-=-=-
Swail supports first-class, full continuation objects. A continuation is an object that stores the "current execution context", and can be used to implement various advanced forms of control flow.
Continuations in Swail basically work as in Scheme: use `with-cc' to obtain the current continuation and call a continuation to return.
Continuations are used to implement restarts in the condition system.
Return `values' from the point at which the continuation `k' was constructed.
Evaluate the forms in `body' with `name' bound to the continuation of evaluating `with-cc', returning the result of evaluating the final form in `body' (but see below).
This form captures the execution context into an object, which can then be passed around or called. Calling the continuation with some values will (re)set the execution context and return those values from the call to `with-cc'. In a program with no other side effects, the effect of calling a continuation is like replacing the `with-cc' form by a form that returns the arguments to the continuation call.
Note that the same `with-cc' form can be evaluated many times; each continuation remembers the context of its own evaluation. Similarly, continuations can be called multiple times, each time resetting the context to the same value. Finally, the extent of a continuation is unlimited: you can call it after evaluation of its `with-cc' form finished.
For example, continuations can be used to implement `break' or `return-from' functionality. Consider a program that computes the product of a list. The product of a list containing `0' is `0', so if we find a zero among the elements we know the answer already and so we can return early. We can implement returning early by capturing the continuation of the computation of the product and calling this continuation with `0' when we find a zero. This gives the following program:
(def-fn faster-product (xs) "Return the product of all elements of the list `xs'." (with-cc break (list:fold (fn () 1) (fn (x xs) (if (= x 0) (break 0) (* x xs))) xs)))
(The name `break' indicates that we're breaking from the multiplication loop.)
Here's a manual implementation of restart-like functionality, showing you can call the continuation multiple times, and outside of the `with-cc' call:
(def-fn some-computation (input) (define try-other-input nil) ; will be set below (define processed-input (process (with-cc k (set! try-other-input k) input))) (if (bad-result? processed-input) (try-other-input (ask-user-for-input!)) (process-more processed-input))))
As long as `(process input)' produces bad results, this asks the user for new input and goes back to the `process' call.
Call `(body k)', where `k' is the continuation associated to the call to `call/cc'. This is used to implement `with-cc'; further explanation can be found there.
Any questions? Contact me:
By email at vierkantor@vierkantor.com