From: Steve Fink [mailto:[EMAIL PROTECTED]]
> 
> Jarkko Hietaniemi wrote:
> > 
> > Allow me to repeat: instead of trying to shoehorn (or piledrive) new
> > semantics onto existing keywords/syntax, let's create something new.
> > The blocks of grep/map/... are special.  They are not quite looping
> > blocks, they are not quite sub blocks, they are different.  Well, to
> > be frank they are just very plain, ordinary, blocks that return
> > their last value, but if we want to introduce both flow control
> 
> So, why not get rid of the specialness? Why can't all blocks return
> their last value?

Yes... why not?


> The ones that currently do not return a value would
> just be given void context. (Just because there's nowhere for 
> the value to go doesn't mean they can't return a value.) And if
> that's done, then
> 
> $val = 1;
> $fact = while ($n) { $val *= $n--; } || $val;
> 
> might not be a horrible idea either.
> 
> Then we would have sub BLOCKs and loop BLOCKs. 'return' would 
> escape the nearest enclosing sub BLOCK and return a value.
> last/redo/next would escape/repeat/continue the enclosing BLOCK
> of any sort, and would be extended to specify the value
> returned. 'last $value' would be equivalent to 'return $value'
> inside a subroutine unless it were enclosed in a loop BLOCK.

I agree... why can't a block be a block? Or put another way, instead of
trying to shoehorn in something new, why don't we take away something old
and treat all the blocks the same under Perl 6? I.e, make loop, bare, and
code blocks able to C<return>, C<yield>, C<next>, C<last>, and C<redo>? And
make all blocks that haven't been short-circuited to return their last
value... 

That would unify bare and code blocks. They'd be like an iterative loop that
executes once and allows a return value.

But loop blocks are still different. When you use a loop control statement
(C<next>, C<last>, or C<redo>) in a loop block, you don't short-circuit the
loop block, you short-circuit the loop statement.

Since blocks can have labels, how about giving built-in functions and
user-defined subroutines their own name as a magic or default label? I know
labels currently can't have package qualifiers. So perhaps this will
conflict with some interals issue. Or maybe it doesn't matter. In any case,
this will leave the programmer some freedom as to whether they are
short-circuiting the block, the loop, or the user-defined function.

Combine the unification of blocks with Tom Christiansen's suggestion which
maintains DWIMish syntax (and doesn't feel like a shoehorn to me at least):

>    return $true && next;
>    return $false && next;
>    return $true && last;
>    return $false && last;
>    return $true && redo;
>    return $false && redo;


Bonus: I no longer have to care about the difference between "code", "loop",
and "bare" blocks...


Here's an user-defined grep subroutine using the proposed changes:

sub mygrep (&@) {
  my ($block, @list, @results) = @_;
  push @results, LOOP: &$block and $_  foreach (@list);
  @results
}

@list = (1,2,3,2,1);

@a = mygrep { $_ <= 2 or last} @list;
@b = mygrep { $_ <= 2 or last LOOP} @list;
@c = mygrep { $_ <= 2 or last mygrep} @list;
@d = mygrep { $_ <= 2 or return $_ && last} @list;
@e = mygrep { $_ <= 2 or return $_ && last LOOP} @list;
@f = mygrep { $_ <= 2 or return $_ && last mygrep} @list;

Resulting I would hope in:

@a = (1 2 2 1)
@b = (1 2)
@c = [exception]
@d = (1 2 3 2 1)
@e = (1 2 3)
@f = (3)


> Oh yeah. do BLOCK is still a third kind, which is transparent to all
> control constructs.

The C<do> block is really more like special anonymous subroutine that takes
no arguments and is special in the sense that it is evaluated before the
loop condition of C<while> and C<until>. I have no idea why it is evaluated
before the loop condition... That seems un-DWIMish.

Garrett

Reply via email to