in reply to Re: "advanced" Perl functions and maintainability
in thread "advanced" Perl functions and maintainability

grep/map are great as list filters, when you want to build one list from another, but they force you to stuff all of your code in one tiny block/expression.

Well, this problem is to build one list from another. Your example builds one list from another. To be clear though: grep is a filter, but map is a transformer.

Neither map nor grep force you to do stuff anything anywhere. There is no magic rule that says it has to fit on one line. You're doing all that work in the foreach anyway (although you're stuffing much more stuff into it).

Consider what is important in the problem. Is it iterating through each element and doing something, or is it creating a new list? In this case, it sure looks like the new list is the point of the exercise, so it should get top billing. When you use map, you emphasize the new list. When you use foreach, you bury the list creation in a bunch of other code. The new list doesn't stand out. Using foreach in this instance may make the syntax readable to anyone with a week's worth of Perl under their belt, but it doesn't make the program logic more readable.

@$newLoop = map { my $hash = { PARTNAME => $_ }; $hash->{SELECTED}++ if $_ eq $row->{title}; $hash; } @$parts;
--
brian d foy <bdfoy@cpan.org>

Replies are listed 'Best First'.
Re^3: "advanced" Perl functions and maintainability
by William G. Davis (Friar) on Dec 13, 2004 at 03:19 UTC

    I disagree. For complex expressions, foreach can always be made more readable than map, because foreach lets you explicitly name the variable that stores each element from the list you're iterating over. Again, this is why I prefer it for anything more than single-statement greps or maps. It may take a little more typing, but in the end, it's clearer and more readable, and yeah, I guess a little easier on the novices too...

      For complex expressions, foreach can always be made more readable than map, because foreach lets you explicitly name the variable that stores each element from the list you're iterating over.
      foreach my $foo (@array) {... $foo ...} map {my $foo = $_; ... $foo ...} @array

        Then why even bother with map to begin with? And no, that isn't as clear. Go back and look at Brian's example. All map blocks need to be evaluated for each element in the list, so when you have a multi-statement block, you end up putting the result at the end, all by itself:

        map { ... $hash; } ...;

        to make sure the block is evaluated properly. This is a side-effect, and it isn't as clear or as readable as an explicit push would be.