http://www.perlmonks.org?node_id=303285


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

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;
vs
$_ /= 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.

Replies are listed 'Best First'.
Re:x6 Think for yourself.
by gwadej (Chaplain) on Nov 04, 2003 at 03:52 UTC

    I guess I've just realized that we are agreeing more than arguing.

    I had a major realization about the list operations in Perl a (relatively) short time ago, and I've been trying to explain it to others (and myself) ever since. I found that some of the problems I was working on simplified drastically when I used the list operators on lists of homogeneous data.

    I think you've helped me to understand that a lot of what I've been trying to say really boils down to another application of the Principle of Least Surprise. The places where I find the list operators to be the most useful are where they can reduce surprise to some extent.

    My example that you quoted above is a good use of map because it does what the reader expects because it follows the right visual pattern.

    The "bad" example you gave above gives the wrong kind of visual feedback and, therefore, causes more surprise. This is also code that is more likely to be corrected incorrectly, because the one who comes after may think they know what it is doing at a glance and be wrong.

    My thanks. You've given me quite a bit to ponder.

    G. Wade
      I believe that many people find easier to understand many list-oriented algorithms if you write them backwards. That is, think of:
      @minutes = map { $_/60 } @seconds;
      as meaning something like:
      @seconds ==> map { $_/60 } ==> @minutes # you could do more complex stuff here... ;
      (Syntax chosen because it is valid Perl 6.)

      When you think this way, then many things that are natural to do with list-oriented operators become more intuitive. For instance merlyn has told me that he thought up the Schwartzian transform by writing it mentally as a pipeline and then rewrote it in Perl. It is only confusing when you see it because our eyes normally scan left to right, top to bottom but the flow of the calls actually goes right to left, bottom to top.

      In Perl 5 that is a useful crutch until your eyes learn how to "parse" things properly. In Perl 6 it is such a useful crutch that I plan to do things that way... ;-)

Re: Re: Re: Re: Re: Re: Think for yourself.
by BrowserUk (Patriarch) on Oct 30, 2003 at 20:15 UTC

    I'm not going to argue with a style judgement, style being a very personal thing, but why do you say that

    $_ /= 60 for @times;

    constitutes bad style?


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    Hooray!

      I say that because now @times has to be interpreted in different ways at different points in your code. A flag for the problem is that now it cannot be given a good name.

      When you change units like that, in some parts of your code it might mean seconds, in some minutes. Or perhaps it was minutes and now it is hours. And you can't even clarify what the units are with a good name name because now the name changes at different points in your code.

      I only consider this kind of side effect acceptable when the variable, array, etc that is being modified was just assigned. Like this:

      my @minutes = @seconds; $_ /= 60 for @minutes;
      Now it is OK because it is clear glancing at the code what @minutes is supposed to be. If it wasn't right for a few instructions, that is because you hadn't finished initializing it yet.

      The two fundamental principles that I would cite here, Side-effects make code harder to understand. and Variables which can't be given simple descriptive names are not well thought-through.

        So, if the logic of the program allows you to avoid naming the seconds prior to the convertion, you would find that acceptable?

        my @minutes = map{ $_/60 } source_of_seconds();

        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "Think for yourself!" - Abigail
        Hooray!