in reply to Using regex in Map function

You'd probably be even more surprised by the result of this:
my @in = qw(aaa bbb ccc); my @out = map { s/.$/x/ } @in; print "@in\n=>\n@out\n";
which prints:
aax bbx ccx => 1 1 1
Yeah, the original is modified. Basically: never modify $_ in a map, and remember that the "output" of s/// is the success count/code. To get what you want, you need to localize $_ and reuse it as the last expression evaluated in the block:
my @in = qw(aaa bbb ccc); my @out = map { local $_ = $_; s/.$/x/; $_ } @in; print "@in\n=>\n@out\n";
which indeed shows:
aaa bbb ccc => aax bbx ccx

Replies are listed 'Best First'.
Re^2: Using regex in Map function
by GrandFather (Saint) on May 02, 2007 at 22:47 UTC

    or better perhaps:

    my @out = map {substr ($_, 0, -1) . 'x'} @in;

    Prints:

    aaa bbb ccc => aax bbx ccx

    DWIM is Perl's answer to Gödel
Re^2: Using regex in Map function
by blazar (Canon) on May 03, 2007 at 09:16 UTC
    To get what you want, you need to localize $_ and reuse it as the last expression evaluated in the block:
    my @in = qw(aaa bbb ccc); my @out = map { local $_ = $_; s/.$/x/; $_ } @in; print "@in\n=>\n@out\n";

    Or use a proper lexical variable:

    my @out = map { (my $s = $_) =~ s/.$/x/; $s } @in;

    AIUI in blead/5.10 the following should also work just in the same manner:

    my $_; # ... my @out = map { s/.$/x/; $_ } @in;
      Hi Blazer & Randal,

      Could you guys please explain why we need to localize $_ inside the map? I am not sure I understand why we need to do this.I seem to get the same result even if I do not localize $_. Is there something I am missing?

      Thanks!
        Hi Blazer & Randal,

        Hi

        Could you guys please explain why we need to localize $_ inside the map? I am not sure I understand why we need to do this.I seem to get the same result even if I do not localize $_. Is there something I am missing?

        It seems to me that merlyn's very clear example explains it quite well. Is there anything about it that you specifically can't understand? Basically map is a filter between an input list and an output one. Due to the way it works, you can use a side effect in the expression or in the code block it comprises to also modify the input list, provided that it's doable, e.g. if the latter is an array, which is a common situation. But as a general rule you don't want to exploit this possibility because it's not what map() is really for. You would probably use an explicit for loop in case you wanted to achieve the same effect. As Tad McClellan recently put it in clpmisc:

        More humorously:

        There are 9 ways to do the same thing in Perl, and 8 of them are no good!

        The following minimal example may also help you:

        #!/usr/bin/perl -l use strict; use warnings; my @in=(1,2,3); my @out1=map {s/^/F/; $_} @in; print "@out1"; my @out2=map {s/^/F/; $_} 1,2,3; print "@out2"; __END__
Re^2: Using regex in Map function
by spandox (Novice) on Feb 05, 2013 at 21:14 UTC
    ************** Bad Program ****
    my @in = qw(a b c d e f g h); print "Start: ",@in,"\n","***RUNNING MAP***\n\n"; my @out = map { s/.$/x/} @in; print "in : ",@in,"\n"; print "out: ",@out,"\n"
    ************* Output ******
    Start: abcdefgh ***RUNNING MAP*** in : xxxxxxxx out: 11111111
    *********************
    Comment #1:
    Use "r" feature on regex
    ************** fixed Program ****
    my @in = qw(a b c d e f g h); print "Start: ",@in,"\n","***RUNNING MAP***\n\n"; my @out = map { s/.$/x/r} @in; print "in : ",@in,"\n"; print "out: ",@out,"\n"
    ************* Output ******
    Start: abcdefgh ***RUNNING MAP*** in : abcdefgh out: xxxxxxxx
    ****************
    Comment #2

    But what if you REALLY wanted the return value of the regex - and not modify the original output? (why? I don't know)
    Localize the input...

    ************** fixed Program ****
    my @in = qw(a b c d e f g h); print "Start: ",@in,"\n","***RUNNING MAP***\n\n"; my @out = map { s/.$/x/} my @temp = @in; print "in : ",@in,"\n"; print "out: ",@out,"\n"
    ************* Output ******
    Start: abcdefgh ***RUNNING MAP*** in : abcdefgh out: 11111111
      You're replying to my note from 2007 with a feature that has only been available for a few releases. Nice.

      -- Randal L. Schwartz, Perl hacker

      The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.

        However, I found the suggestion of using the /r modifier very helpful in 2016!