Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options

Why do I need a local variable in map function

by Anonymous Monk
on May 23, 2019 at 07:31 UTC ( #11100402=perlquestion: print w/replies, xml ) Need Help??

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

Hi Monks,

I have a function with should select files by a given list of extension. I wrote a program, which did not work. After playing a little around I found a working solution (using a local variable: my $x). But I do not understand, why my first version is not working.

Can you help me explaining the difference between this two versions:

In the first version the expression(@ext) is replaces by '1';

In the second version the expression(@ext) is correct. ('f.*\\.txt$', 'f.*\\.txt.*$')

Thanks for your help !!!

use strict; use warnings; use Data::Dumper qw(Dumper); $\="\n"; my @ext; my @list=('f1.txt','f2.txtx','f3.xtxt','x1.txt'); my $ex="f*.txt,f*.txt*"; print " Version 1: Not working--------------------------------"; @ext=map { $_=quotemeta($_).'$'; s/\\\*/.*/;} split(/,/,$ex); + # <<<<<< compare this line print "qr=".Dumper(\@ext); foreach my $e(@ext) { foreach my $f(@list) {print "Match: ($e) => $f" if ($f=~m/$e/); }} print " Version 2: working--------------------------------"; @ext=map { my $x=quotemeta($_).'$'; $x=~s/\\\*/.*/g; $_=$x;} split(/,/ +,$ex); # <<<<<< compare this line print "qr=".Dumper(\@ext); foreach my $e(@ext) { foreach my $f(@list) {print "Match: ($e) => $f" if ($f=~m/$e/); }}

Replies are listed 'Best First'.
Re: Why do I need a local variable in map function
by haukex (Bishop) on May 23, 2019 at 07:41 UTC

    s/// returns the number of substitutions made, so that's what that map block is returning. Although it's generally not considered good practice to modify the original list by modifying or assigning to $_ in a map block, the first version could be written as map { $_ = quotemeta($_) . '$'; s/\\\*/.*/g; $_ } to achieve the desired result. Alternatively, as of Perl 5.14, you can say s///r to have the regex return the modified string, e.g. map { my $x = quotemeta($_) . '$'; $x =~ s/\\\*/.*/gr }.

    Update: Note that your second regex includes /g, while your first one does not; I've added it to both my examples.

    Update 2: Or even just map { quotemeta($_).'$' =~ s/\\\*/.*/gr } or map { "\Q$_\E\$" =~ s/\\\*/.*/gr }

      Thanks for the perfect answer.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://11100402]
Approved by haukex
Front-paged by Corion
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (5)
As of 2020-08-03 12:59 GMT
Find Nodes?
    Voting Booth?
    Which rocket would you take to Mars?

    Results (27 votes). Check out past polls.