• Continuations

    From Lawrence D'Oliveiro@21:1/5 to All on Wed Jun 5 07:05:44 2024
    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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)