Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister

Re: Re: Think for yourself.

by gwadej (Chaplain)
on Oct 06, 2003 at 03:24 UTC ( #296848=note: print w/replies, xml ) Need Help??

in reply to Re: Think for yourself.
in thread is the use of map in a void context deprecated ?

The main reason I tend to use map is to signal to the reader of the code that this is an operation on a list not just on a set of values that are conveniently represented as an array.

In other words, to me, map and grep carry extra semantic value to future maintainers of the code. (In most cases, Wade-future does not really remember what Wade-past had in mind.<grin/>)

To me, your first example implies that we are transforming a list. The second implies we are transforming the elements of a list. Although the results are the same to the computer, to the programmer the meaning may be very different.

G. Wade

Replies are listed 'Best First'.
Re: Re: Re: Think for yourself.
by tilly (Archbishop) on Oct 06, 2003 at 03:37 UTC
    Then we extract different semantic value from the same code. To me both grep and map make me start looking for where the return is going, because the return is likely to be the point of the operation. By contrast a for loop tells me that the action of the loop is what I should focus on. This bias is strong enough that while I am happy to have loops have side-effects, I will go out of my way to rewrite maps or greps with side-effect in their blocks to be regular loops instead.

    If you are not the only maintainer of your code, it might be worthwhile to find out what both constructs mean to them. Remember that meaning is highly dependent on the context that the reader brings to the document. If people around you read it the same way, then the map solution may well be more maintainable in your environment. If they read it differently, then it may be better to retrain your intuition to match theirs. This kind of issue is one where having people be on the same page matters more than what page everyone is on.

      I agree... the use of map in a void context also makes me look for how the return value is used, because to me, getting a return list is the main reason for using map. This type of distinction reminds me of the section in perlstyle that says:

      Just because you CAN do something a particular way doesn't mean that you SHOULD do it that way. Perl is designed to give you several ways to do anything, so consider picking the most readable one. For instance

      open(FOO,$foo) || die "Can't open $foo: $!";

      is better than

      die "Can't open $foo: $!" unless open(FOO,$foo);

      because the second way hides the main point of the statement in a modifier. On the other hand

      print "Starting analysis\n" if $verbose;

      is better than

      $verbose && print "Starting analysis\n";

      because the main point isn't whether the user typed -v or not.

      To me, using map in a void context seems like "hiding" the main point of the code. And I'll point that out to people, but there are much more flameworthy transgressions. :-)

      -- Mike

      XML::Simpler does not require XML::Parser or a SAX parser. It does require File::Slurp.
      -- grantm, perldoc XML::Simpler

        Oops. I apparently did not make myself clear.

        I rarely use map or grep in a void context. When I said that I see map and grep and operations on a list. I mean it in much the same way that + is an operation on a number.

        When I need to transform a list into a new list, I tend to think of map. To me, the foreach approach focuses more on the individual elements of a list than on the list as a whole.

        That being said, I will break my own preferred approach any time it makes the code clearer.<grin/>

        G. Wade

      I'm sorry. I appear to have added to the confusion, rather than clarifying. I should have begun by saying that I avoid using map or grep in void context.

      What I was commenting on was your suggestion that the only reason for using those operators was that they are more concise and show a better grasp of Perl.

      An example of what I was trying to say is the code example below.

      my @minutes = map { $_ / 60 } @seconds;

      In the foreach style, this would be

      my @minutes = (); foreach my $sec (@seconds) { push @minutes, ($sec / 60); }

      To me, the first signals the intent to transform a list of times in seconds into an equivalent list in minutes. The second has pretty much the same effect, but I have to read the code to see what the output is. In the first case, it seems obvious (to me, at least) that the output is the left side of the assignment.

      Although this may seem like a simple example. I find many times that I can use these operators to reduce the noise characters in code like this. Sometimes that reduction is enough to make the overall code clearer by not spending space on relative minor pieces of logic.

      Granted, if the code inside the block gets complicated enough, I may change to the foreach style to emphasize the fact that this is not a simple transformation.

      I see this as a Perl idiom that can convey information to the maintainer when used carefully. I do agree that it can be horribly misused. (The less I say about that the better.<grin type="embarassed"/>

      G. Wade
        I think that you emphasized my point. As I said, To me both grep and map make me start looking for where the return is going because the return is likely to be the point of the operation. Your code example is:
        my @minutes = map { $_ / 60 } @seconds;
        I glance at this, and indeed the return is the point of the operation. Just the words, "minutes", "map", "60" and "seconds" makes it blindingly obvious.

        However it is even more obvious because your code fits a visual pattern that I expect to see. Even a trivial code example with map or grep used for side-effects forces me to think. Compare

        map {$_ /= 60 } @times;
        $_ /= 60 for @times;
        Yeah, both are bad style. But of them, the latter is significantly easier for me to read, and not just because of length.

        On an unrelated stylistic note, if the contents of a complex mapping become complex, rather than go to a foreach loop, I am inclined to write a function for the body of the map, name it well, and insert it into the map. This emphasizes that the operation is not simple, indicates what it is, and makes it clear that the point of the code is to return something. I find this clearer, YMMV.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://296848]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (6)
As of 2018-06-22 21:34 GMT
Find Nodes?
    Voting Booth?
    Should cpanminus be part of the standard Perl release?

    Results (124 votes). Check out past polls.