Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

Re: Re: playing with map

by jeroenes (Priest)
on Mar 09, 2001 at 13:51 UTC ( [id://63214]=note: print w/replies, xml ) Need Help??


in reply to Re: playing with map
in thread playing with map

Ahum, grep can be used to modify the list. From perlfunc (at my system, 5.6):

Note that, because `$_' is a reference into the list value, it can be used to modify the elements of the array. While this is useful and supported, it can cause bizarre results if the LIST is not ...

Jeroen
"We are not alone"(FZ)

Replies are listed 'Best First'.
(tye)Re: playing with map
by tye (Sage) on Mar 09, 2001 at 21:07 UTC

    Well, kinda. With grep, for each item you can only:

    • Leave the item alone and not include it in the result
    • Modify the original item and not include it in the result
    • Include the original item, unmodified, in the result
    • Modify the original item and include this exact same modification in the result
    With map you can do all of the above and also do:
    • Leave the item alone and include one or more values in place of that item in the result
    • Modify the item and include one or more values in place of that item in the result, with the ability to even include the original (unmodified) item in the result.
    So using grep to return something other than a subset of the original list is quite restricted and is probably an indication that you shouldn't be using grep. (:

            - tye (but my friends call me "Tye")
      So using grep to return something other than a subset of the original list is quite restricted and is probably an indication that you shouldn't be using grep. (:

      I have been guilty of writing

      do_something() if (grep /something/, @array);
      is this a "wrongly" used grep? Should I be writing something like-
      foreach (@array){ &do_something() and last if /something/; }
      ... the grep seems easier on the eye IMO. Is it OK if you know the data source is always going to be small?

        do_something() if (grep /something/, @array);

        Actually, that doesn't bother me much at all. It is probably slower in most cases than some alternatives, but I'd probably only go about optimizing for that if I strongly suspected that @array was going to contain a whole lot of entries, many of which match /something/. But it is probably faster for cases where @array is quite large and most of the time none of its entries match /something/ (since the grep solution doesn't have to "dispatch" as many opcodes), so "premature optimization" could cost you here. Though I won't swear to anything without seeing benchmarks for a specific problem on a specific platform.

        It would be neat if grep could tell that it is in a "Boolean context" and just give up as soon as it finds the first match. Unfortunately, I don't think Perl has context information other than 1) void, 2) scalar, 3) list, or 4) list assignment of size N, that is automatically tracked. I think such tracking is planned (perhaps waiting for Perl6 these days), so we may see such an automatic optimization in the future.

        And I guess I should update my blanket statement on grep to be "So using grep to return something other than a subset of the original list (or, in a scalar context, the number of elements in that subset) is quite restricted and may be an indication that you shouldn't be using grep." With your code often being one of the exceptions in my book. (:

                - tye (but my friends call me "Tye")
        I'm not qualified to say that it's wrong. I will say that it doesn't seem like the right tool. Just for an example, consider the hazard of accidentally doing something like:
        my @b = grep { s/apples/oranges/ } @a;
        If what you meant was to have a @b basket of oranges, and an  @a basket of apples, you'll be quite unhappy to find that grep has eaten all of your apples.

        mkmcconn

Re (tilly) 3: playing with map
by tilly (Archbishop) on Mar 09, 2001 at 21:20 UTC
    What tye said. Just because you can do something doesn't mean that it isn't also a really stupid idea to do it. Using map or grep in void context is a sign of someone who has picked up bad habits.

    UPDATE
    I was asked why talking about modifying the input list triggered comments about void context from me and tye. Here is why. The typical bad idiom you see is to use a grep in void context to change the input list. Hence the alarm. Note that it is usually a bad idea to modify the input list when not in void context, but occasionally it may be natural to do that. For instance the input list is temporary, and you want to both filter and modify in an obvious way. Here is an example of a case where it would fit:

    return grep s/^FOR_PRINT://, <FILE>;
    In my experience these cases tend to be rare.

    UPDATE 2
    merlyn is right. I would have to work harder to come up with a place where modifying the input list makes sense. Given that I am not feeling well, I don't feel like doing that, and given that I think it is a bad idea, I don't think I should bother...

      return grep s/^FOR_PRINT://, <FILE>;
      But even that can be trivially written as:
      return map /^FOR_PRINT(.*)/s, <FILE>;
      And thus not lose 5 style points for altering $_, which in my all-too-often experience spits out an "attempt to modify read-only value" when I least expect it.

      -- Randal L. Schwartz, Perl hacker

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://63214]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others scrutinizing the Monastery: (11)
As of 2024-04-18 08:48 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found