Probably I'm doing something totally wrong, but is there some way to modify and combine regexes
using subroutines? The program below wouldn't compile.
sub a(Regex $r1) {
return rx/ <$r1> a /
}
my regex letter_b { b };
my $new = a(letter_b);
say $new;
Looking at the documentation for Regex
, it says:
A named
regex
can be defined with the regex declarator followed by its definition in curly braces. Since any regex doesCallable
introspection requires referencing via&
-sigil.my regex R { \N }; say &R.^name; # OUTPUT: «Regex»
Also, the Grammar
documentation (for the concept, not the Type), it explains more about this:
The main ingredient of grammars is named regexes. While the syntax of Perl 6 Regexes is outside the scope of this document, named regexes have a special syntax, similar to subroutine definitions:
my regex number { \d+ [ \. \d+ ]? }
In this case, we have to specify that the regex is lexically scoped using the
my
keyword, because named regexes are normally used within grammars.Being named gives us the advantage of being able to easily reuse the regex elsewhere:
say so "32.51" ~~ &number; # OUTPUT: «True» say so "15 + 4.5" ~~ / <number> \s* '+' \s* <number> / # OUTPUT: «True»
So, to pass your named regex as a parameter into your a
subroutine, all you have to do is prefix it with an ampersand:
my $new = a(&letter_b);
# ^
# This is what you need!
say $new;
say so "ba" ~~ $new; # OUTPUT: «True»
say so "ca" ~~ $new; # OUTPUT: «False»
Starting with @callyalater's conclusion[1]:
my $new = a(&letter_b);
# ^
# This is what you need!
In the rest of this answer I address two follow on questions I imagine folk might still have if @callyalater's answer doesn't work for them.
Why?
What's with the error message?
Almost all programming languages have named functions you can declare once and then call any number of times. Many support functions as first class values. Raku does. This means raku allows you to refer to an already declared function in two fundamentally distinct ways:
To "call" a function, write its name. It will actively do what it's declared to do.
To just "refer" to a function as a first class value, prepend a &
. The reference will be passively passed on.
Thus:
sub foo { say 42 }
say foo; # 42
say &foo # &foo
Before I can continue, I must note that things get slightly tricky when writing about these things in English or whatever human language. First, by definition in English, if we write anything then we're referring to it! Also, one can't actually "call" foo
in English. So the convention is to write just foo
when it should be obvious by context whether we mean calling it (in raku, foo
) or merely "referring" to it (in raku, &foo
).
Unlike other languages, in raku regexes are functions. In the second line of the following code, letter_b
is being called, not merely referred to:
my regex letter_b { b }
letter_b
So in my $new = a(letter_b);
, the regex letter_b
is being called, and the result of that call would be passed to the call of a
, whereas in my $new = a(&letter_b);
, you're merely passing a reference to letter_b
.
Too few positionals passed; expected 1 argument but got 0
There are several classes of functions in raku. One is Regex
. The Regex
class is a sub-class of Method
:
my regex foo { ... }
say &foo ~~ Method; # True
my method bar { ... }
say &bar ~~ Method; # True
What happens if you call the method bar
without an invocant?:
bar # Too few positionals passed; expected 1 argument but got 0
That's why you get that error message if you call letter_b
without an argument/invocant.
(If you declare a method in a grammar, it automatically gets the grammar class/object as its invocant; remember that grammars are classes.)
[1] I often review an answer of mine if someone upvotes it long after I wrote it. Someone just did. If I see a way to improve the collective usefulness of our comments/answers, eg by deleting or editing my question, I do so, sometimes by rewriting it to work as a comment relative to the accepted answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With