> If one were looking for the first matching item, last would work:
   > 
   >    grep { /pat/ and last } @foo
   >    # return()s the value of $_=~/pat/, which will be true

Huh? I can't see how that could work unless you change the existing
semantics of C<and> and C<last>.

Let's take a step back and analyse the problem. We need a way to allow a
C<grep> block to do all of the following:

        * reject the current element and continue
        * accept the current element and continue
        * reject the current element and then short-circuit
        * accept the current element and then short-circuit

*and* be consistent with existing semantics.

I would propose that the C<grep> operation should short-circuit if the
block throws an exception, with the value of the expection determining
whether the final invocation of the block should accept the element it
was filtering:

    # existing (non-short-circuiting) semantics...
        @smalls = grep { ($_ < 2) } @numbers;

    # short-circuit after first acceptance...
        @smalls = grep { ($_ < 2) and die 1 } @numbers;

    # short-circuit after first rejection...
        @smalls = grep { ($_ < 2) or die 0 } @numbers;


This would extend naturally to cater to C<map> and C<reduce> blocks, which
must return a value, rather than a flag:

    # existing (non-short-circuiting) semantics...
        @squares = map { $_ ** 2 } @numbers
        $product = reduce { $_[0] * $_[1] } @numbers


    # short-circuit after result reaches 100 (but include that result)...
        @squares = map { my $sq = $_ ** 2; $sq >= 100 ? die $sq : $sq }
                       @numbers;
        $product = reduce { my $pr = $_[0] * $_[1]; $pr >= 100 ? die $pr : $pr }
                          @numbers

    # short-circuit when result reaches 100 (and exclude that result)...
        @squares = map { my $sq = $_ ** 2; $sq >= 100 ? die : $sq }
                       @numbers;
        $product = reduce { my $pr = $_[0] * $_[1]; $pr >= 100 ? die : $pr }
                          @numbers


I'll be happy to change the C<reduce> RFC if people like this alternative.

Damian

Reply via email to