http://qs1969.pair.com?node_id=1178871

perlancar has asked for the wisdom of the Perl Monks concerning the following question:

If grep were to be made shortcutting in boolean/scalar context (returning only the first result, or returning just true/false), would it break many programs? I would prefer a shortcutting grep, making it behave like List::Util's first but faster for larger lists.

Also, what do you guys think of this idiom to simulate shortcutting of grep:

if (eval { grep {$_==$wanted and die} @ary}, @$) { say "match" }

Also, how about shortcutting map() too in boolean context? Although that makes less sense.

Replies are listed 'Best First'.
Re: Shortcutting grep in boolean context
by tybalt89 (Monsignor) on Jan 03, 2017 at 21:10 UTC

    Alternate idiom:

    $_ == $wanted and say("match"), last for @ary

      `for @a` also avoids putting every element of the array on the stack like `map @a` and `grep @a` do.

      Ah yes, this is a nice idiom, and to use it in an expression, one can use e.g. do:

      if (do { my $found; $_ == $wanted and $found = 1 and last for @ary; $found }) { say "match" }'

        To avoid a temporary variable:

        if( sub{ $_ == $wanted and return 1 for @ary; 0 }->() ) { say "match" +}
Re: Shortcutting grep in boolean context
by Anonymous Monk on Jan 03, 2017 at 20:50 UTC
    would it break many programs?

    Not using grep for its side effects is only a best practice, so yes, I think that people are using it for its side effects, and that it would be a breaking change in enough programs to make it unfeasible. Or, at least it would be a big enough change and break from tradition that you'd never convince P5P to make the change :-) What's wrong with List::Util?

      As the list gets larger, the overhead of copying the list into @_ increases.
Re: Shortcutting grep in boolean context
by Anonymous Monk on Jan 03, 2017 at 20:55 UTC
    In scalar context, grep returns the number of times the expression was true. Counting things is an extremely common usage of grep. And in "boolean context" you still have the issue of when grep's code block is used for side effects.

      OK. Well, for large lists I'll settle with foreach + last + do block then :) And when the lists are not large, just grep.