The difference between /.../ and m/.../
From Rexes # Lexical conventions :
m/abc/; # a regex that is immediately matched against $_ rx/abc/; # a Regex object /abc/; # a Regex object
In other words, these are /.../ and rx/.../ , which are synonyms, and not /.../ and m/.../ :
/.../ and rx/.../ return the specified regular expression as a Regex object, without matching it with anything at the moment.m/.../ immediately matches the specified regular expression with the string stored in the variable $_ (the so-called "theme"), and returns the result as Match or as Nil if there was no match.
Demonstration:
$_ = "Foo 123"; say m/\d+/; # ๏ฝข123๏ฝฃ say m/\d+/.^name; # Match say /\d+/; # /\d+/ say /\d+/.^name; # Regex
Explanations and comments regarding your code
Using regex modifiers
but recently a file ending in Csv has appeared. Therefore, I tried not to be case sensitive.
my @csv_files = dir( test => m:i/ csv $ / ); Use of uninitialized value of type Any in string context. Methods .^name, .perl, .gist, or .say can be used to stringify it to something meaningful. in block <unit> at <unknown file> line 1
This code immediately matches the regular expression regarding the topic $_ calling area that is not initialized. This includes converting it to a string (which triggers the Use of uninitialized value of type Any in string context warning) and returns Nil because there is no match. So you essentially call the dir( test => Nil ) function dir( test => Nil ) .
To make it work, use rx or use the adverb :i inside the regular expression:
my @csv_files = dir( test => rx:i/ csv $ / );
my @csv_files = dir( test => / :i csv $ / );
Blocks like smart sockets
I found that I can fix this by putting a block around the corresponding expression:
> my @csv_files = dir( test => { m:i/ csv $ / } );
This also works. What is going on here is:
{ ... } creates a block that takes one argument (which is available as $_ inside the block).m:i/ ... / inside the block matches $_ and returns Match .- Since
m:i/.../ is the last statement in the block, its Match becomes the return value of the block. - The
dir function called dir accepts any smart matches, which includes not only Regex objects, but also Block objects (see the documentation for the smart-match ~~ operator ).
Using Regex as a Bool
However, if I used a block around the original expression, it does not match bare //, but it works with m //:
> my @csv_files = dir( test => { / csv $ / } ); []
When a block is used as smart matches, it is first called, and then its return value is forced to Bool : True means that it matches, and False means that it is not.
In this case, your block always returns a Regex object.
Forcing a regular expression object to a logical one immediately matches it with the current $_ and returns True if the corresponding regular expression, and `False if it is not:
say /\d+/.Bool; # False $_ = "123"; say /\d+/.Bool; # True
So, in your code, the regular expression is checked again on $_ , and not on file names:
$_ = "abc"; .say for dir test => { / \d+ / } # Returns no filenames $_ = "abc 123"; .say for dir test => { / \d+ / } # Returns all filenames
Filter files by their extension
I am looking for CSV files in a directory. At first I searched for files ending in csv this way (all code is shown in Perl 6 REPL):
> my @csv_files = dir( test => / csv $ / );
This is not just a search for files with the CSV extension, but all files that end with three letters cvs , including those that look like foobarcsv or foobar.xcsv .
Here are two best ways to record if you only need CSV files:
my @csv-files = dir test => / ".csv" $ /;
my @csv-files = dir.grep: *.extension eq "csv"
Or case-insensitive version:
my @csv-files = dir test => / :i ".csv" $ /;
my @csv-files = dir.grep: *.extension.lc eq "csv"