This came up in a discussion on London.pm about Damian's Perl 6 talk,
which led us to wonder about control exceptions and how they're
handled. At the moment, control exceptions fall into the 'vaguely
handwavy' category, and what follows is my attempt to work out how I
think they should behave...

Damian Conway <[EMAIL PROTECTED]> writes:

> Lusercop wrote:
> 
> > It has to be said that watching someone talk about this is rather easier
> > than trying to follow the exegeses and apocalypses (IMO). Certainly, in
> > the absence of a real, live Perl6 interpreter this is the case.
> 
> Hmmmm. Maybe that makes *me* the real, live Perl 6 interpreter at the moment. ;-)
> 
> 
> > One thing I am slightly confused about, though, is that if {} now delimits
> > a subroutine, what happens to this bit of code:
> 
> The implicit question seemed to be if raw blocks and C<if> blocks
> and C<while> blocks and C<do> blocks, etc. are all really
> closures/subroutines, what happens if they have a C<return> in them?
> 
> The answer is that C<return> throws a "control exception". The named control
> structures catch and re-propagate this to the surrounding subroutine. Raw
> blocks do the same thing. So the effect is exactly as in Perl 5: a C<return>
> in a controlled or raw block causes the surrounding subroutine to
> return.

So, when you're writing a looping construct for a class that will be
used like:

    method lazy_search ($a_collection, $a_target) {
        ...
        $a_collection.do -> $each {
            $each =~ $a_target and return $each;
        }
        return;
    }

ie, where a 'return' inside the arg block should return to the calling
scope, but where a normal 'fell off the end of the block' should just
continue 'round the block. How do we do that? Will there be some
cunning calling convention which will allow us to interrogate the
return value of a try to find out how it was arrived at?

    method do ($self : &block) {
        for $self.members &block;
        CATCH Control::return { throw }
    }

Hang on, that should just work shouldn't it? Just take advantage of
the fact that the current C<for> already has those semantics and it
seems I'll need to think a good deal harder to come up with something
concrete that'd require knowledge of how something got returned.

Thinking about this, I suppose that one could arrange it so that a
C<try> *always* sets $!, either to some error type exception that was
thrown, or to the control exception that escaped the block. If one
then overloaded C<< operator:? >> for control exceptions so that they
were false in a boolean context one could continue to write code like:

    try &block; 
    if ($!) {...}

and have it work as expected, but still be able to get at the control
exceptions in the (rarer) occasions they were needed.

-- 
Piers

   "It is a truth universally acknowledged that a language in
    possession of a rich syntax must be in need of a rewrite."
         -- Jane Austen?

Reply via email to