Allison wrote:

> As I was talking to Damian, he came up with a compelling semantic
> argument why we would want C<else> blocks to follow, which is a question
> that needed to be faced since we rejected C<continue>.

Specifically, the semantic argument with that idea is that CAPITAL blocks
attach automatic behaviours to a surrounding scope, but the C<ELSE> behaviour
is specifically *not* associated with the surrounding block. Or rather:
specifically associated with the *not* of the surrounding scope.

Either way, that would make embedded C<ELSE>s seem highly counter-intuitive to me.


> And the discussion of scope led to (what I think is) an interesting
> tidbit on NAMED blocks...

Which I presume was that the proposed usage:

    while $result.get_next() -> $next {
        # do something with $next...
        ELSE {
            if $next eq "xyz572" {
                print "We defined this value, $next, as false for obscure purposes.";
                print "No loop was executed. Just wanted to let you know.";
            }
        }
    }

would actually be a (very subtle and nasty) bug!

The construct:

        -> $next {...}

is, of course, an anonymous subroutine declaration. Hence C<$next> is a parameter,
the binding of which only occurs when the subroutine is invoked (i.e. on each
iteration). However, if the C<while> condition fails, the subroutine *isn't*
invoked, so C<$next> isn't bound, so the nested C<ELSE> block (even if it were
fired off separately) wouldn't work as expected.

This leads me to conclude that a normal (trailing, un-nested) C<else> is a
much more reasonable construct for a C<while> -- and at least arguable for a C<for>.

The argument in its favour is simply that it eliminates two not-unusual -- but
very annoying -- constructions involving repeated tests. Namely:

    if (some_test) {
        while (some_test) {
            ...
        }
     }
     else {
        ...
     }

and the more error prone (because it assumes C<some_test> is idempotent):

    while (some_test) {
        ...
    }
    unless (some_test) {
        ...
    }

And it replaces them with a very DWIMish alternative:

    while (some_test) {
        ...
    }
    else {
        ...
    }

I haven't seen those annoying constructions used as often with C<for> loops,
but I imagine they might well occur more frequently in Perl 6, where lazy
iterators will make C<for> loops the preferred choice in a far wider range of 
circumstances.


> And something just feels right about C<else> blocks on loops. It fits in
> with that Perlish pattern of allowing structures that feel so natural
> you wonder why no other language ever allowed them.

Yes. That's one of Larry's greatest talents: doing the obvious-in-hindsight. :-)

Damian

Reply via email to