Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses

Map not giving me what I thought it would.

by the_0ne (Pilgrim)
on Jun 02, 2001 at 08:39 UTC ( #85155=perlquestion: print w/replies, xml ) Need Help??
the_0ne has asked for the wisdom of the Perl Monks concerning the following question:

Sorry for the newbie-ish question monks, but I'm having trouble understanding the results I'm getting using map. This...
map { s/^-// } @ARGV; print join ("\n", @ARGV) . "\n";
...when I run './ -foo -bar' gives me...
foo bar
Which is what I would think it should, but then why does this not work...
my @array = map { s/^-// } @ARGV; print join ("\n", @array) . "\n";

This gives me...
1 1
I'm not understanding why the first code snippet works but the next code snippet, which the only difference is setting the results of the map to an array, gives me scalar output.

Again, sorry for the newbie-ish question. I looked through other posts, examples using map and it doesn't look like I'm doing anything different.

There has to be a very simple explanation, I'm just not seeing it though.

Thanks again monks.

Replies are listed 'Best First'.
Re: Map not giving me what I thought it would.
by dvergin (Monsignor) on Jun 02, 2001 at 08:46 UTC
    The return value of s/// is not the changed string but the number of successful substitutions.

    In the case of your s/^-// the return value will always be 0 or 1.
    But in the case of:   s/something/something else/g   it could easily be a higher number.

    my $string = 'abacadaeaf'; my $result = $string =~ s/a/x/g; print $result; # prints 5
    Update: Note that wog is correct in saying that a successful match will return a TRUE value. But it can be something other than 1 if /g is specified.
Re: Map not giving me what I thought it would.
by wog (Curate) on Jun 02, 2001 at 08:47 UTC
    What's happening here is that when you do:

    my @array = map { s/^-// } @ARGV;

    two things are happening. First, the subtitution is changing $_ which is actually a reference to an element in @ARGV. Like in foreach when you change $_ in a map or grep it affects the item in the array being based to map or grep. As for the values in @array, they are always 1 in your example because the result of s/^-// is 1 (true) when the substitution succeeds, and false otherwise.

Re: Map not giving me what I thought it would.
by converter (Priest) on Jun 02, 2001 at 18:21 UTC

    In the interest of making life easier, CPAN modules for processing of command line options include: Getopt::Std and Getopt::Long. These modules are very handy for processing command line options of the most commonly used forms.

    With that out of the way, in order to make map work the way you'd like it to, you can use a pattern expression with capturing parentheses:

    #!/usr/bin/perl print "\@ARGV: [@ARGV]\n"; my @my_args = map { /^-(.*)/ } @ARGV; print "\@my_args:\n"; print "$_\n" for @my_args;

    map evaluates the block in list context. The pattern with capturing parantheses, when evaluated in list context, returns either the captured text, or an empty list. What this means is that new elements are added to @my_args only when the pattern matches. Notice that the argument "baz," which doesn't begin with minus, is not added to @my_args.


    $ ./ -foo=bar -bar baz
    @ARGV: [-foo=bar -bar baz]

Re: Map not giving me what I thought it would.
by damian1301 (Curate) on Jun 02, 2001 at 08:54 UTC
    As the above two mentioned, it is because of the substitution's return value. So, instead of using your way of joining the values, you can just put the whole thing one map with the same functionality and without the extra newline.

    my @array = map {s/^-//;$_.="\n"}@ARGV;

    Simple stuff, basically just does what you were doing then uses the "$var = $var.stuff" operator (which I love dearly =) to append a newline onto the end of each line.


    Tiptoeing up to a Perl hacker.
    Dave AKA damian

Re: Map not giving me what I thought it would.
by princepawn (Parson) on Jun 02, 2001 at 08:55 UTC


    shorten this:
    map { s/^-// } @ARGV; print join ("\n", @ARGV) . "\n";

    to this

    print join "\n", map { s/^-// } @ARGV;

    now for an answer

    In the first case, you were modifying $_ and as a result modifying@ARGV in place. Since you printed @ARGV, you got what you expected.

    however, the second time, you received a number indicating the number of succesful matches. Check out the /gmodifier you want - to match more than once in the string.

    Here is a simpler example that shows what was happening each time you applied your regexp to $_

    $_ = 'aaaaaaaaaaa'; my $x = s/a//; print "$x\n";
Re: Map not giving me what I thought it would.
by adamsj (Hermit) on Jun 02, 2001 at 09:16 UTC
    What's happening is that map is giving you the result of what happens inside the parentheses, not the final value of $_. The regex matches once each time, so the result is 1 each time. I'm not a frequent map user, but try this (untested) instead:

    my @array = map { (split(/^-/,$_))[0] . (split(/^-/,$_))[1] } @ARGV;

    I think that'll work, assuming you want your command line arguments in @array whether they have leading hyphens or not, but, even if it does work, it's lousy code. Surely there's a better way, but I'm too tired to see it.


    They laughed at Joan of Arc, but she went right ahead and built it. --Gracie Allen

Re: Map not giving me what I thought it would.
by the_0ne (Pilgrim) on Jun 02, 2001 at 09:16 UTC
    Thank you all very much. I fully understand exactly what was happening now. It's one of those thing where you hit yourself in the forehead and go, so that's what it was doing....

    I was expecting to get slammed for the newbie-ish question, but by the answers it doesn't look like anybody even thought about it.

    Thanks again (++ for everybody).

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://85155]
Approved by root
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (4)
As of 2018-06-24 19:39 GMT
Find Nodes?
    Voting Booth?
    Should cpanminus be part of the standard Perl release?

    Results (126 votes). Check out past polls.