Groups | Search | Server Info | Login | Register


Groups > comp.lang.postscript > #4008

Continuations

Path csiph.com!news.swapon.de!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From Lawrence D'Oliveiro <ldo@nz.invalid>
Newsgroups comp.lang.postscript
Subject Continuations
Date Wed, 5 Jun 2024 07:05:44 -0000 (UTC)
Organization A noiseless patient Spider
Lines 64
Message-ID <v3p2o7$s5n4$1@dont-email.me> (permalink)
MIME-Version 1.0
Content-Type text/plain; charset=UTF-8
Content-Transfer-Encoding 8bit
Injection-Date Wed, 05 Jun 2024 09:05:44 +0200 (CEST)
Injection-Info dont-email.me; posting-host="4516e25990465832a6742c15b1bf965a"; logging-data="923364"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX195ZBkHQZuSuV7ckl6Ano9g"
User-Agent Pan/0.158 (Avdiivka; )
Cancel-Lock sha1:FXB84S9Twaecs8JfCNWdsJaLm9U=
Xref csiph.com comp.lang.postscript:4008

Show key headers only | View raw


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


Thread

Continuations Lawrence D'Oliveiro <ldo@nz.invalid> - 2024-06-05 07:05 +0000

csiph-web