blackjudas has asked for the wisdom of the Perl Monks concerning the following question:

Ok, I'm calling uncle...

I'm addmittedly not the best programmer in the world, I certainly enjoy working with perl and indulging the TMTOWTDI fact that Perl extends to all. I have previously posted regarding the map function. I now have successfully used it throughout my code, making it more readable and more efficient.
Recently I ran into the following problem, I was helping a fellow learn his first steps through perl and the logical approach to truth in perl. When I ran into a map problem, illustrated below:
my @delete_list = map {$_ =~ s/^delete_check_//} (grep /^delete_check_ +/, keys %session);
I had expected all the keys that contained the 'delete_check_' string at the beginning to be stripped and the remaining values to be populated into the @delete_list array. I instead got a relative number of 1's where I expected the results. I know that map returned a status, meaning, 1 "I've done the job you have requested". So, at this point I went through some of my old code and came up with:
my @delete_list = map {/^delete_check_(.*)/} (grep /^delete_check_/, k +eys %session);
This approach worked beautifully as I had expected. What I'm curious about is, what exactly do I need to pass to map inside the block to return the correct result? I'm still on the fence here regarding my full understanding of the map function. Therefore I'm worried that I have a bigger underlying issue of understanding when it comes to expressions and what exactly they are. Is it that map is one of the few functions in perl that needs special care on how you "express" yourself with it?


BlackJudas

Edit kudra, 2002-05-15 Changed title

Replies are listed 'Best First'.
(jeffa) Re: How to express myself
by jeffa (Bishop) on May 14, 2002 at 21:43 UTC

      Or you can omit map altogether...

      my @delete_list = grep s/^delete_check_//, keys %session;

          --k.


•Re: How to express myself
by merlyn (Sage) on May 15, 2002 at 00:31 UTC
    I'd skip the grep: it's redundant:
    my @delete_list = map /^delete_check_(.*)/, keys %session;
    This works because the regex match is in a list context. If it matches, you get back $1. If it fails to match, you get an empty list. And it disappears. {grin}

    -- Randal L. Schwartz, Perl hacker

      Yes very true merlyn I was just using it as an example for the person I was teaching, explaining how to make one function feed another a list.

      BlackJudas
Re: How to express myself
by thelenm (Vicar) on May 14, 2002 at 21:59 UTC
    map evaluates the block in list context. Whatever the code inside the block returns in list context is what map will see.

    The substititution operator s/// returns the number of substitutions made (in this case 1). So map will get a list of 1s. You could still use the substitution operator if you can force the code inside the block to return the string you want, like this:

    my @delete_list = map {s/^delete_check_//; $_} (grep /^delete_check_/, + keys %session);
    Now the block returns $_ after doing the substitution, so it should map correctly.

    When you use the match operator m// in list context without the /g modifier and with capturing parentheses, it returns a list of the matches. That's why your second example works, because in list context the code block returns the text you're looking for. Here's another simple example of m// returning a list of matches in list context:

    my $str = "Helloooo, nurse!" my ($greeting, $recipient) = $str =~ m/^(\w+),\s+(\w+)/; print "Greeting: '$greeting', Recipient: '$recipient'\n";
Re: How to express myself
by csotzing (Sexton) on May 14, 2002 at 21:53 UTC
    s/// returns the number of substitutions performed, which might be where all the 1's came from. :-)