From: Damian Conway [mailto:[EMAIL PROTECTED]]
> 
> From: Garrett Goebel 
> > @passed = grep { 2 > $_ and last } (1, 2, 3, 2, 1);
> > 
> > would leave 
> > @passed = (1, 2)
> 
> I believe the above would leave:
> 
>       @passed = ();
> 
> since on the first call to the block 2 > 1 is true, so the C<last> is
> executed, which terminates the C<grep> immediately.
> 
> > instead of the current behaviour which would be
> > @passed = (1, 2, 2, 1) 
> 
> That's not the current behaviour.

Yes, and my example was bad anyway. Sloppy, sloppy... What I
meant to write (which is still useless anyway) was: 

> > @passed = grep { $_ > 2 and last } (1, 2, 3, 2, 1);
                     ^^^^^^

Under Perl 5...

> With the C<last> you either get an exception

Can't "last" outside a loop block at ...

Which is what I suppose we are proposing could be changed. Would that imply
that in C<map>, C<grep>, and C<reduce> the block be treated as a iterative
loop's block? 

I have practically no knowledge of the Perl internals, implementation
details, or the specific terminology to use with regards to Perl internals.
I'm just an outsider looking in. Please correct my terminology if needed,
and feel free to suggestion ideas for implementation. I had the mistaken
impression, that this topic was easy enough that even I could fully grok it.


> Just to note that RFC 76 (Builtin: reduce) also proposes this
> mechanism as a means of short-circuiting C<reduce>.

Hmm... what RFC 76 says is:

> If the reduction subroutine is ever terminated by a call to C<last>,
> the enclosing C<reduce> immediately returns the last reduction value
> (i.e. C<undef> on the first reduction call, $_[0] otherwise)

Which I read to mean that C<reduce> would be treated as an iterative looping
construct? 

Since only loops can be exited with C<last>. Would that mean that:
C<grep>, C<map>, and C<reduce> would "be" iterative loops like C<while>,
C<until>, C<for>, and C<foreach>... or would someone have to invent some new
internal representation for C<last> to treat them as such?


> or an exit from the surrounding block (and in either case
> @passed is not reassigned at all).

Yes... I should have actually tried this before making up what I thought it
would be.  

I suppose the fact that I inherently have a hard time shaking the assumption
that the blocks in C<grep> and C<map> should be treated as iterative
loops... is a vote in favor of allowing one to think of them as such. After
all, they are iteratively looping through a list of elements... What am I
missing here? How is this different than C<for> and C<foreach> other than
syntax? Is there any history behind why they aren't already iterative loops?


> > We are already advised not to use last within eval {}, sub {},
> > do {}, grep {}, and map {}, but this might break some
> > obfuscated code which depends on it. I'm not to sure how
> > this could be handled in a Perl 5->6 translation...
> 
> Have p52p6 name *every* block and label *every* C<next>, 
> C<last>, and C<redo>.

Okay, I wasn't sure it needed to go that far, but it is probably far easier
to implmement and more reliable. I'll update the RFC.

Now that I'm actually checking how the "advice" (Camel Book, 3rd Ed, pg 735,
C<last>) is inforced by the interpreter... the results are as follows:

eval { last };     # [no error]
do   { last };     # Can't "last" outside a loop block at
sub  { last }      # [no error]
grep { last } (1); # Can't "last" outside a loop block at
map  { last } (1); # Can't "last" outside a loop block at

Garrett

Reply via email to