in reply to Re: map in void context
in thread map in void context

Side-effects are something to be avoided when programming.
In Perl? So, you'd prefer to avoid assignment, print statements, regular expressions, and even fetching the value of a variable?

There are programming languages that are more suitable for avoiding side-effects. But programming in Perl while avoiding side-effects makes as much sense as writing English novels while avoiding vowels.

I also like my code to be as self-documenting as possible.
Who doesn't? For me having code as much self-documenting as possible doesn't mean map in void context isn't.
I find map is less than optimal for both of these reasons.
$sum += $index{$_} for split(//, $word);
The map-in-void context equivalent would be
map $sum += $index{$_}, split(//, $word);
I see as many side-effects as the code using 'for', so your example doesn't prove your first reason. In fact, the 'side-effect' reason people often come up with doesn't make any sense. If you do map EXPR, LIST or map BLOCK LIST, the side-effects are in EXPR or BLOCK. The 'for' equivalents are EXPR for LIST and for (LIST) BLOCK. Same EXPR and BLOCK. Same side-effects.

As for documentation (or clearness) issues, I see differences between:

map {BLOCK} LIST
and
for (LIST) {BLOCK}
and that's the order of BLOCK and LIST. If I find the action more important, I prefer map {BLOCK} LIST, as it lists the statement(s) first. If I want to put the focus on the data, I use for (LIST) {BLOCK}. (There's also a difference in context, map gives list context, for void context, but that's seldomly an issue).

I hardly ever use the map EXPR, LIST construct though (regardless of context), as it doesn't clearly separate the action from the data.

Replies are listed 'Best First'.
Re^3: map in void context
by kyle (Abbot) on Dec 17, 2008 at 16:45 UTC

    I don't consider assignment to have a "side effect". Assignment is the effect. It might have a side effect if I'm working with a tied variable, I guess, but that's out somewhere else.

    Another difference between for and map is what happens when the BLOCK modifies the array that it's iterating over.

    my @x; # loops once @x = qw( x ); map { push @x, 'x' } @x; # loops forever @x = qw( x ); push @x, 'x' for @x;
      Hi, kyle -

      I seldom disagree with what you say ... in this case, however, I do, since assignment does indeed have a side effect since it returns a logical true when it was successful. Otherwise the following code would not work:
      if ( my $a = 2 ) { print "Assigned a value to $a"; }

      (Yes, I know it produces a warning ... but it still runs ;-) Any comments?

      Regards -

      Pat
        Any comments?

        That's like saying a subroutine has a side effect if it returns a value. If you start to argue that the value of an expression is a side effect, you'll prove that no language can be pure if it allows you to write expressions. (You can argue that if you want, but I'm not sure it gets you anywhere.)

        It's not really returning "true", it's returning the value on the right side of the assignment.

        my $x = 2; print "\$x is '$x'\n"; if ( $x = 0 ) { print "\$x = 0 is true\n"; } else { print "\$x = 0 is false\n"; } print "\$x is '$x'\n"; __END__ $x is '2' $x = 0 is false $x is '0'

        This behavior is why you can say "$x = $y = $foo" and set both $x and $y to whatever is in $foo.

        If you consider the "effect" of assignment to be returning the value of the right hand side, then perhaps changing the value of the variable is a side effect. I don't see it that way, however.

      Another difference between for and map is what happens when the BLOCK modifies the array that it's iterating over.

      One could argue that this difference is just a side-effect of the specific implementation. ;)

      I don't consider assignment to have a "side effect". Assignment is the effect.
      So,
      map {$sum += $_} @array;
      is side-effect free?
        I don't consider assignment to have a "side effect". Assignment is the effect.
        So,
        map {$sum += $_} @array;
        is side-effect free?
        This seems disingenuous. While I agree that arguing that assignment is “side-effect free” seems a little strange, your example isn't just assigning, it's mutating. Even in the purest of functional languages, x = 5 is OK (I think!); but x += 1 isn't.
Re^3: map in void context
by ikegami (Patriarch) on Dec 17, 2008 at 17:24 UTC

    So, you'd prefer to avoid assignment,

    I don't know what side effects you are talking about for assignments.

    print statements,

    I'm not fond of how print changes $!, but it's much more convenient than the alternative. There's also a very high level of consistency with other like functions. system is where it goes overboard ($?).

    regular expressions,

    I don't use $1, etc. I use the match operator in list context instead.

    and even fetching the value of a variable?

    Memoizing is a harmless side-effect.

    I see as many side-effects as the code using 'for'

    As I see it,
    The purpose of for is to affect something (necessarily external) repeatedly.
    The purpose of map is to transform a list.
    You may see things differently, but it was clear that I was explaining how I see things.

    A reply falls below the community's threshold of quality. You may see it by logging in.