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

Reply via email to