Click here to get back home

FAQ 6.21 What's wrong with using grep in a void context?

 HomeNewsGroups | Search | About
 comp.lang.perl.misc    Post an article   get this group's latest topics as an RSS feed add this group's latest topics to your My MSN content add this group's latest topics to your My Yahoo content
Subject Author Date
FAQ 6.21 What's wrong with using grep in a void context? PerlFAQ Server 03-20-2008
Posted by Peter J. Holzer on March 22, 2008, 6:23 am
Please log in for more thread options
> wrote:
>> PerlFAQ Server wrote:
>> > 6.21: What's wrong with using grep in a void context?
>> >
>> > The problem is that grep builds a return list, regardless of the
>> > context. This means you're making Perl go to the trouble of
>> > building a list that you then just throw away. If the list is
>> > large, you waste both time and space. If your intent is to iterate
>> > over the list, then use a for loop for this purpose.
>> >
>> > In perls older than 5.8.1, map suffers from this problem as well.
>> > But since 5.8.1, this has been fixed, and map is context aware -
>> > in void context, no lists are constructed.
>>
>> So why not simply make grep context aware too? Seems grep would benefit
>> from this just as much, if not more, as map.
>
> You're missing the point. grep makes no sense in void context because
> it exists to output a list.

The same is true for map. If it makes no sense for grep, then it also
doesn't make sense for map. Conversely, if it does make sense for map,
then it also makes sense for grep.

> Although the Perl internals might recognize and optimize that, why
> should we have to clutter Perl with optimizations for people doing the
> wrong thing? It's dump that we had to do it with map() because so many
> people were doing it wrong.
>
> If you want to go a list to run some block of code, use foreach().

I fully agree with this. foreach is right tool for the job.

However, the wording of the FAQ suggests to me that *conceptually* its
completely ok to use grep or map instead of foreach, you just shouldn't
do it for performance reasons (and as of 5.8.1, map has been "fixed", so
use map instead of foreach at will. TIMTOWTDI! Yeah!).

So I'd rather write that the other way around:

When grep (or map) is used in a void context, its return value is
discarded. All that remains is the loop over its input list.
Therefore

        grep { X } @arr

and

        map { X } @arr

do ultimately the same thing as

        do { X } for @arr;

but the latter is clearer.

Also, grep (and before perl 5.8.1, also map) builds the return list
even in void context, so using the for loop is likely to be faster,
too.

On a related note, I agree with szr that grep should be optimized for
scalar context. Constructs like

my $num_matches = grep /foo/ @arr;

or

if (grep /foo/ @arr) { ... }

are quite common. Instead of building a list, a simple counter can be
used. In the second case, grep could even short-circuit and return true
after the first match (although that is likely to break existing code
which relies on side-effects).

        hp

Posted by szr on March 22, 2008, 10:03 am
Please log in for more thread options
Peter J. Holzer wrote:
>>> PerlFAQ Server wrote:
>>>> 6.21: What's wrong with using grep in a void context?
>>>>
>>>> The problem is that grep builds a return list, regardless of the
>>>> context. This means you're making Perl go to the trouble of
>>>> building a list that you then just throw away. If the list is
>>>> large, you waste both time and space. If your intent is to
>>>> iterate over the list, then use a for loop for this purpose.
>>>>
>>>> In perls older than 5.8.1, map suffers from this problem as
>>>> well. But since 5.8.1, this has been fixed, and map is context
>>>> aware - in void context, no lists are constructed.
>>>
>>> So why not simply make grep context aware too? Seems grep would
>>> benefit from this just as much, if not more, as map.
>>
>> You're missing the point. grep makes no sense in void context because
>> it exists to output a list.
>
> The same is true for map. If it makes no sense for grep, then it also
> doesn't make sense for map. Conversely, if it does make sense for map,
> then it also makes sense for grep.

Exactly true.


>> If you want to go a list to run some block of code, use foreach().
>
> I fully agree with this. foreach is right tool for the job.

Wont argue there.

> However, the wording of the FAQ suggests to me that *conceptually* its
> completely ok to use grep or map instead of foreach, you just
> shouldn't do it for performance reasons (and as of 5.8.1, map has
> been "fixed", so use map instead of foreach at will. TIMTOWTDI!
> Yeah!).

Yep. It's all about TIMTOWTDI, that's what always made Perl great :)

> So I'd rather write that the other way around:
>
> When grep (or map) is used in a void context, its return value is
> discarded. All that remains is the loop over its input list.
> Therefore
>
> grep { X } @arr
>
> and
>
> map { X } @arr
>
> do ultimately the same thing as
>
> do { X } for @arr;
>
> but the latter is clearer.

Yep, though some might argue the map/grep version is more elegant, and
easily chainable & nestible (think working on multi-dim arrays, where
you might nest, with at least the outter most being in voice context.

> Also, grep (and before perl 5.8.1, also map) builds the return list
> even in void context, so using the for loop is likely to be faster,
> too.
>
> On a related note, I agree with szr that grep should be optimized for
> scalar context. Constructs like
>
> my $num_matches = grep /foo/ @arr;
>
> or
>
> if (grep /foo/ @arr) { ... }

Exactly. Especially if each element is a ref, you can do something to
the refs. You can do this with 'map' in an optimized way now it seems.
'map' and 'grep' would do the same thing in this regard, though I don't
know if that warrents the optimization, but it may still be a good idea
to do so if it doesn't harm performance.

> are quite common. Instead of building a list, a simple counter can be
> used. In the second case, grep could even short-circuit and return
> true after the first match (although that is likely to break existing
> code which relies on side-effects).


How about having something along the lines of a pragma to control that
behavior (like use strict/no strict.)

--
szr



Similar ThreadsPosted
FAQ 6.21: What's wrong with using grep in a void context? November 23, 2004, 12:03 am
FAQ 6.21 What's wrong with using grep in a void context? January 23, 2005, 6:03 pm
FAQ 6.21 What's wrong with using grep in a void context? May 16, 2005, 5:03 pm
FAQ 6.21 What's wrong with using grep in a void context? August 1, 2005, 4:03 am
FAQ 6.21 What's wrong with using grep in a void context? October 10, 2005, 10:03 pm
FAQ 6.21 What's wrong with using grep in a void context? November 28, 2005, 11:03 am
FAQ 6.21 What's wrong with using grep in a void context? January 17, 2006, 5:03 pm
FAQ 6.21 What's wrong with using grep in a void context? May 4, 2006, 3:03 am
FAQ 6.21 What's wrong with using grep in a void context? September 1, 2006, 9:03 pm
FAQ 6.21 What's wrong with using grep in a void context? November 11, 2006, 9:03 pm

Our other projects:

Art Dolls, Fairies and Mermaids - Sunnyfaces.net

Roy's Linux, Programming and Search Engines messages

1-Script XML SitemapXML Sitemap