Rod Adams wrote:
Well, that's another explanation that jives with my understanding of them..... But I still don't have an idea of when I would actually want to use them in something I'm writing.

You can use them to implement all sorts of interesting control flow constructs.


For example, here's an implementation of exceptions (though not the one we'll be using):

    our Continuation $try_cont;

    sub try(&try_block) {
        temp $try_cont = take Continuation;
        unless defined $! {
            try_block();
        }
    }

    sub catch(&catch_block) {
        if defined $! {
            catch_block($!);
        }
        undef $!;
    }

    multi sub throw(Exception $except) {
        $!=$exception;
        throw();
    }
    multi sub throw() {
        $try_cont();
    }

    try {
        throw new Exception: "Whoa there!";
    }
    catch {
        print "Caught exception: $!";
    }

(Disclaimer: untested, and I've never actually used continuations.)

Note here that we don't want the changes to $! to be undone--that's what determines whether try_block or catch_block is executed (this time around). If the $! changes were undone, then try_block would either be called repeatedly until it finally managed to succeed. In the case of the try_block used here, the program would get stuck in an infinite loop.

That example's a bit obvious, since continuations are similar to setjmp()/longjmp(), and one of the things those functions are often used for is exceptions. But there are other cases, too...

Suppose, for example, you're writing a disk checker (fsck, scandisk, etc.). Like all such programs, yours has the infuriating habit of starting over every five seconds:

    for @ARGS -> $partition {
        my &cont := take Continuation;

        my $timer=new Timer: &cont
            :interval<<5sec>> :repeat(1);

        do_scan($partition);
        #Aren't race conditions fun, children?

        #Like this'll ever happen.
        $timer.cancel();
    }

Could this be done with redo()? Sure. But realize that *redo() itself could be implemented with continuations*. Nearly any control flow construct can. (I think a goto() can't, but that's about it.) Loops, exceptions, and subroutines can all be implemented in terms of continuations--but so can almost any other control flow construct you can think of, and most likely some you can't.

--
Brent "Dax" Royal-Gordon <[EMAIL PROTECTED]>
Perl and Parrot hacker

Oceania has always been at war with Eastasia.

Reply via email to