Bart wrote:
> >The last operator doesn't return anything does it? It immediately
> >exits the loop/block in question.
This is correct.
> But then, what is the value that would be returned to grep()? If you use
> 0 as the last value evaluated inside the block, grep() would return an
> empty list, 0 in scalar conetxt, and all your tests woukld be in vain.
>
> So: should
>
> scalar grep { 1 and last } LIST
>
> return 1, if LIST is not empty, and
No, that expression ought to evaluate to 0. See below.
> scalar grep { 0 or last } LIST
>
> return 0?
Yes.
> If that is not dealt with, last inside a grep block will never work.
Here's my understanding of how it would work.
A C<grep> such as:
@array = grep BLOCK LIST
is equivalent to:
@tmp = ();
foreach (LIST) { push @tmp, $_ if do BLOCK }
@array = @tmp;
That similarity would not change in any way under the proposal
(except to be made stronger!)
If BLOCK contained a C<last>, the invocation of that C<last> would
*immediately* cause the implicit C<foreach> to terminate,
*without* pushing any value onto @tmp from the final execution of
the code in BLOCK.
So:
grep { $_<2 or last } @numbers;
returns the first N elements of @numbers up to *but not including*
the first element that is >= 2.
This implies that C<last> cannot be used to short-circuit *after* a
specific value is recognized (and allowed through). It can only be used
to short-circuit *when* a specific value is recognized (and *before* it
is allowed through).
That is not an onerous constraint on inequalities: < vs <= gives you
the control you need. But it makes "short-circuit as soon as C<grep>
lets through a specific value" ugly:
my $seen;
$has_odd_elem = grep { $seen && last; $_%2 && ++$seen } @numbers;
:-(
Damian