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

Hello Monks,

I am baffled as to why this code isn't working; it just returns "1, 1, 1" when I have three elements in the array. I use virtually the same regex elsewhere and it works fine. If I switch to "uc", that works, too; so I know I still have the correct values in my ARGV. Can someone give me an explanation? (I'm just trying to strip the provided names down to the file names without directory structure).

print $out_file "Lexicons: ", join(', ', map{s/.*\///} @ARGV[FIRST_LEX +ICON .. $#ARGV]), "\n";
Thanks!

Replies are listed 'Best First'.
Re: Map with Regex Replace
by Corion (Patriarch) on Aug 08, 2013 at 13:50 UTC

    See Regexp-Quote-Like-Operators. s/// returns the number of substitutions made. The /r option makes it return the modified string, but it's "only" available since 5.14 I believe.

    As a workaround for an older Perl, consider

    map { (my $foo=$_)=~ s!.*/!!; $foo } ...

    or, in your case, consider File::Basename or Path::Class.

      Regarding the older Perl workaround, Corion's solution can roughly equivalently be expressed as
      map { s!.*/!!; $_ } ...
      providing that the array you are feeding is not read only (i.e. @ARGV works but qw|1.2 3.4 5.6| would require the lexical misdirection) and you don't care if it mutates.

      I think the more natural way of expressing this, since you are really operating on every element, would be to write

      s!.*/!! for @ARGV; print "Lexicons: ", join(", ", @ARGV[FIRST_LEXICON .. $#ARGV]), "\n";
      The general rule of thumb/best practice-y thing is you should only use maps when you use the return value; and for/foreach when you are operating on each element. The lexical assignment in Corion's solution essentially turns the operation into something mappier.

      #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

      Ah! That /r did it (I'm on 5.16). Perfect! Thanks!