Re: Style question: map versus foreach

From: Abigail (abigail_at_abigail.nl)
Date: 11/10/03


Date: 10 Nov 2003 22:30:01 GMT

Darin McBride (dmcbride@naboo.to.org.no.spam.for.me) wrote on MMMDCCXXIII
September MCMXCIII in <URL:news:RKQrb.361373$6C4.143831@pd7tw1no>:
:: Abigail wrote:
::
:: > Darin McBride (dmcbride@naboo.to.org.no.spam.for.me) wrote on MMMDCCXXIII
:: > September MCMXCIII in <URL:news:FRCrb.356754$pl3.261426@pd7tw3no>:
:: > __ Abigail wrote:
:: > __
:: > __ No, you're right. I suppose you overlooked the "that's the concept"
:: > __ part of that paragraph. Context rules in perl. But that doesn't mean
:: > __ that context rules in the maintainer's head when trying to decipher
:: > __ what was written.
:: >
:: > If you're going to assume the maintainer doesn't know basic concepts
:: > of Perl, all bets are off. Then one might want to avoid hashes and
:: > regexes too.
::
:: True to a point. However, there is no cleaner way to do hashes or
:: regexes. There is a clearer way to do map in void context: foreach.

But could you give an objective reason why foreach is "clearer" than
map (after defining what "clearer" is)? Or is it your own preference?
What makes foreach cleaner than while? Or is while cleaner than
foreach? Which one ought to go? Or can we have foreach, for, while,
until, goto, and bare blocks, but not map in void context?

:: And that's the crux, too. If there was no foreach, then it would be
:: obvious to all comers that map in void context is used for a particular
:: purpose.
::
:: However, the general rule is to use map for return values and foreach
:: when you don't need the return value. And that's what most people are
:: likely to think. Try reading perldoc perlstyle a bit... a few tidbits:
::
:: o 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.

You can do loops in the following ways:

 1 C style for
 2 Perl style foreach
 3 for statement modifier
 4 while
 5 until
 6 bare blocks
 7 s///g
 8 m//
 9 goto
10 map
11 grep

Don't pick on map in void context. Could you please pick one, and make
a case against the other 10, and not just map?

:: The main point of map is the return value. The main point of foreach
:: is the iteration over an array (no return value implied).
::
:: o Avoid using grep() (or map()) or `backticks` in a void
:: context, that is, when you just throw away their
:: return values. Those functions all have return val-
:: ues, so use them. Otherwise use a foreach() loop or
:: the system() function instead.
::
:: I think this is the whole debate. Unfortunately, there's no real
:: explicit justification here.

Which makes it just the personal preference of one man, doesn't it?

:: > "Obvious" is something subjective. *YOU* might find one way of doing
:: > something more obvious than doing it another way. But that doesn't
:: > mean it's true for everyone. Could you please explain why you find
:: > map in void context so non-obvious? Do you think map in general is
:: > non-obvious, or do you only get confused when the context is void?
:: > What about other functions in void context? Are they non-obvious too?
:: > Or is it only map that's non-obvious?
::
:: Given that map and foreach do almost exactly the same thing with only
:: the desired contexts being different, it makes sense to me that one
:: would use the version one desires based on that context difference.
:: Thus, when I see map in void context, the first thought in my mind is
:: "they didn't get the return from map!".

Ah, yes. Logical. There are thousands and thousands of user defined
functions whose return value isn't collected. There are many Perl
defined functions and operators whose return value isn't collected.

Noone ever makes a fuss. But if the function of which the return
value isn't collected is called "map", hundreds of Perl programmer
brains go into overload, and the programmers start running around
like chickens without their heads. "They didn't get the return from
map! They didn't get the return from map! Keep your daughters inside!
Keep your daughters inside! The end of times in coming! The antichrist
has arrived!"

I really don't get it. map in void context isn't doing anything else
than the countless of other functions in void context that are called
because of their side effects. Yet it sparks gigabytes of discussions.

:: Then, after scrutinising the
:: map's block (as it's usually a block not an expression), I may figure
:: out that they intended to have void (e.g., only doing it for the side
:: effect). And then, if that's not the source of the problem, I can go
:: on.

But if the function wasn't called "map", but "zeebleflup", and it was
used in void context, would you get confused as well? What if it was
called "apply_this_function_over_the_elements_of_a_list"?

:: However, if they had used foreach to begin with, I might have been able
:: to skip over the code altogether knowing that "ignoring the return" is
:: exactly what was intended.

Again, why do you assume that if map was used in void context the
programmer was in error, and you have to confirm yourself it wasn't the
case, and you don't have this Pavlov reaction with other functions? What
makes map trigger this behaviour?

:: > Is there anyone who can explain why map in void context is confusing,
:: > but other functions aren't?
::
:: Simply have your code say what you mean rather than trick the virtual
:: machine into doing what you want by side effect.

If I write:

    map {BLOCK} LIST;

I write *exactly* what I mean. I want to map an operation over a list.
It simple can't be named simpler.

:: In general, side
:: effects make code harder to understand.

Then you shouldn't be programming in Perl. Because in Perl, you can't
do much useful without side effects.

Abigail

-- 
perl -we '$@="\145\143\150\157\040\042\112\165\163\164\040\141\156\157\164".
             "\150\145\162\040\120\145\162\154\040\110\141\143\153\145\162".
             "\042\040\076\040\057\144\145\166\057\164\164\171";`$@`'


Relevant Pages

  • Re: Style question: map versus foreach
    ... @@> But could you give an objective reason why foreach is "clearer" than ... it couldn't have been in void context. ... There are many Perl ...
    (comp.lang.perl.misc)
  • Re: Style question: map versus foreach
    ... but I was originally using map() in ... > void context and figured that was bad practice. ... > foreach loop even in void context? ... Depends on the version of perl you employ. ...
    (comp.lang.perl.misc)
  • Re: Style question: map versus foreach
    ... The only real difference between map and foreach is that map returns a ... value, while foreach doesn't. ... only data I have to work with is whether we're in void context or not, ... Good if you're mapping one space (array) onto another space. ...
    (comp.lang.perl.misc)
  • Re: Style question: map versus foreach
    ... >> The only real difference between map and foreach is that map returns a ... don't create it in the first place and just use foreach. ... Which version of perl are you using? ... equivalent function exists that documents that there is no return (or ...
    (comp.lang.perl.misc)
  • Re: Style question: map versus foreach
    ... There is a clearer way to do map in void context: foreach. ... the desired contexts being different, it makes sense to me that one ...
    (comp.lang.perl.misc)