> 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