http://qs321.pair.com?node_id=11119058


in reply to Perl::Critic says don't modify $_ in list functions and other things

For me, the critical thing to realize about a statement like
    my @array = map { $_ =~ s/^[\*\+-] (.+)/$1/; ... } @another_array;
is that it is operating on the elements of @another_array at the same time it's generating a new array to assign to @array. So the function

sub fancy_map { my ($opt, $list) = @_; map { if (ref($_)) { fancy_map($opt, $_); } else { my $before = $opt->{'before'} ? $opt->{'before'}.' ' : ''; my $after = $opt->{'after'} ? ' '.$opt->{'after'} : ''; $_ = $before.$_.$after; } } @{$list}; }
which is passed an array by the reference $list is also operating on the referent of $list!

Consider:

c:\@Work\Perl\monks>perl -wMstrict -le "my @list = qw(foo bar baz boff quux); print qq{original: @list}; ;; my @spookified = spooky_aaad(\@list); print qq{returned: @spookified}; print qq{original: @list}; ;; sub spooky_aaad { my ($array_ref) = @_; ;; return map { $_ =~ s{ \A (.) (.*) \z }{\U$2\E$1}xms; $_; } @$array_ref; } " original: foo bar baz boff quux returned: OOf ARb AZb OFFb UUXq original: OOf ARb AZb OFFb UUXq
(Update: Also, the statement
    my @another_array = map { chomp($_);  $_; } @original_array;
is equivalent to the statements
    my @another_array = @original_array;
    chomp @another_array;
    chomp @original_array;
because $_ is aliased to the elements of @original_array. In the case of a statement like
    my @list = map { chomp($_); $_ } <$fh>;
this doesn't matter: the <$fh> expression creates a temporary list that is fed to map and then vanishes. But in other cases... See also ikegami's reply.)

Any time I see code structured in this way, my buggy-sense starts to tingle. If you're happy with the operation of your code, that's fine with me; you can just ignore or (I think) turn off the specific critique. Just be aware that pitfalls lurk here.

Update: Oops... In my haste to answer, I overlooked the latter questions of your post.

...why the expression form of eval is discouraged?
String eval is looked upon askance because it is an open invitation to all kinds of mischief if your data is not absolutely trustworthy — and even then many programmers would avoid it, preferring alternatives that may be slightly more roundabout, but that are a whole bunch safer.
my $var = "foo" if 'some condition';
This inadvertantly allowed syntax leaves $var in an undefined state of existence. It used to be used to simulate a persistent, "static" variable within a function; state is used for this purpose now, and the old usage is officially Frowned Upon.


Give a man a fish:  <%-{-{-{-<