On the one hand, 'map' returns an output list that results from applying some block of code to an input list. This leads to the often-repeated mantra "don't use map in a void context". (Why? Well, let's not digress...)

On the other hand, 'map' will alter the elements of the input list if its block of code modifies $_ in any way, because within the block, $_ functions as a reference to a list element on each iteration -- and of course this is often (usually) how 'map' is used. This can lead to the sort of trouble discussed in this recent meditation, when the input list happens to contain read-only data.

One could argue that this dual result from the mapped code block -- doing in-place editing of the input list and also returning the edited list -- seems to be overdoing it, or is somewhat redundant.

There are many examples of functions (not just in Perl, but generally) that alter the contents of variables in-place and return the original (unaltered) values, or that return altered values and leave the input variables unchanged -- that is, their changes are applied either to the input or to the output, but not to both.

So, maybe this is just a "SoPW" question: is there something that works like 'map' but will not alter the input list? (Or, less intuitively, modify the input list and return the list of unaltered values?)

Apart from cases where the input list contains read-only elements, there are common situations where it would be handy to map one list into another, and have both versions of the list available for later use. To the best of my knowledge, the alternatives for doing this are:

# ------------------ # FIRST ALTERNATIVE: @out_list = @in_list; map { s/foo(.*?)bar/$1 baz/ } @out_list; # ACK!! ARRGGHH!! map in void context! how bad is that? # (Well, seriously: how bad _is_ that, compared to the # other alternatives below? But let's not digress...) # ------------------- # SECOND ALTERNATIVE: @out_list = map { s/foo(.*?)bar/$1 baz/ } split /\x0/, join("\x0",@in_ +list); # okay, map is used "correctly", and this even works when # the input list and block processing are numeric, but... # seems like too much busy-work just to protect @input_list # from being altered by map. # ------------------ # THIRD ALTERNATIVE: @out_list = map {$j=$_; $j=~s/foo(.*?)bar/$1 baz/; $j} @in_list; # at this point, might as well use "foreach (@input_list) {...}" inste +ad
Are there other (better) alternatives? If there aren't, shouldn't there be? Is it just silly of me to yearn for this sort of thing?

In reply to A "harmless" alternative to 'map{}'? by graff

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.