Groups | Search | Server Info | Login | Register
Groups > comp.lang.postscript > #4008
| From | Lawrence D'Oliveiro <ldo@nz.invalid> |
|---|---|
| Newsgroups | comp.lang.postscript |
| Subject | Continuations |
| Date | 2024-06-05 07:05 +0000 |
| Organization | A noiseless patient Spider |
| Message-ID | <v3p2o7$s5n4$1@dont-email.me> (permalink) |
Continuations are a generalization of control constructs: from a common
primitive, you can build such things as loops (with exits), exceptions,
and even coroutines.
The way I have implemented this in GXScript is with the “cexec” operator:
this takes a procedure as an argument, like “exec”, but before calling it,
it pushes a continuation object on the stack. Invoking this object will
transfer control to the point immediately following the cexec call that
created it.
Example:
{
/Count 5 ldef
/Top null ldef
{/Top exch lstore} cexec
{
/Break exch ldef
Count =
/Count Count 1 sub lstore
Count 0 eq {Break} if
Top
}
cexec
}
exec
Output:
5
4
3
2
1
But that’s a clunky way to have to write a loop every time. So why not
package up the creation of the continuations in a reusable procedure:
/DoLoop
{
/Proc exch ldef
/Top null ldef
{/Top exch lstore} cexec
{Proc Top} cexec
}
ddef
DoLoop will take your loop-body procedure as argument, and execute it
repeatedly, each time pushing a continuation that can be used to exit the
loop, until you invoke that continuation. Example use:
/Count 5 ddef
{
/Break exch ldef # always pop arg even if not used
Count =
/Count Count 1 sub lstore
Count 0 eq {Break} if
}
DoLoop
The output is the same as before.
The source is here <https://bitbucket.org/ldo17/gxscript/> if you want to
have a play.
Back to comp.lang.postscript | Previous | Next | Find similar
Continuations Lawrence D'Oliveiro <ldo@nz.invalid> - 2024-06-05 07:05 +0000
csiph-web