© Copyright Kirk Rader 2023. All rights reserved.
Engines from Continuations
A practical application of continuations to implement sophisticated flows of control.
In Engines from
Continuations, Dybvig and Hieb [1988] describe how the flow of control
abstraction known as "engines" can be implemented using Scheme's first-class
continuations. The following source code is adapted from one of the versions of
make-engine
described by Dybvig and Hieb.
In this implementation, an engine is simply a Scheme procedure of three
arguments. For example, the following code will invoke the procedure named
thunk
as an engine:
(letrec ((return
(lambda (value remaining-ticks)
(display "engine returned ")
(display value)
(newline)))
(expire
(lambda (new-engine)
(display "engine expired, ")
(display "use the given new ")
(display "engine to resume")
(newline)))
(thunk
(lambda ()
(decrement-timer)
(display "engine running")
(newline))))
((make-engine thunk) 1 return expire))
This is different from simply calling thunk
directly in that it will be given
a finite amount of "fuel" in the form of "timer ticks." If thunk
completes
before the engine runs out of fuel, it will call return
. If the fuel runs out
before thunk
completes, expire
will be invoked with a new engine that can be
used to resume the interrupted computation in thunk
.
See the warnings in the source code comments regarding the use of
decrement-timer
in procedures passed to make-engine
.
This implementation differs from that in the original paper in a few ways, all thoroughly documented in comments in the source code. Of particular interest:
-
Eliminates the need for the
make-simple-engine
helper function defined and used in the paperSpecifically,
make-engine
wraps the invocation of the procedure it was passed in a call toengine-return
-
Adds
engine-expire
for symmetry withengine-return
Calling
engine-expire
causes the currently executing engine to pass control to its expiration handler immediately in the same way that callingengine-return
causes an immediate invocation of the return handler.