Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I interpolate a variable into a Perl 6 regex?

Tags:

regex

rules

raku

Synopsis 05 mentions that Perl 6 doesn't interpolate variables into a regex, but you can associate an external variable with a pattern. The docs don't mention this feature as far as I can tell. I think people are still going to want to build up a pattern from a string somehow, so I'm curious how that would work.

Here's a program that demonstrates what happens now. I don't know if that's what is supposed to happen or what anyone intended. I insert a variable into a pattern. If you look at $r with .perl, you see the variable name. Then, I apply the pattern and it matches. I change the variable's value. Now the pattern doesn't match. Change it to something else that would work, and it matches again:

my $target = 'abcdef';

my $n = 'abc';
my $r = rx/ ( <$n> ) /;

# the smart match like this doesn't return a Match object
# https://rt.perl.org/Ticket/Display.html?id=126969
put 'rx// directly: ',
    $target ~~ $r
        ?? "Matched $0" !! 'Misssed';

# now, change $n. The same $r won't match.
$n = 'xyz';

put 'rx// directly: ',
    $target ~~ $r
        ?? "Matched $0" !! 'Misssed';

# now, change back $n. The same $r does match.
$n = 'ab';
put 'rx// directly: ',
    $target ~~ $r
        ?? "Matched $0" !! 'Misssed';

If that's what it's supposed to do, fine. The docs are light here, and the tests (the de facto spec) aren't sophisticated for long range behavior like this.

I could do extra work to close over a copy (and maybe more work than I show depending on what is in $n), which I find unperly:

my $r = do {
    my $m = $n;
    rx/ <$m> /;
    };

But, I'd still like to have a way to "finalize" a pattern (oh my god, I just asked for /o to come back). A method in Regex perhaps. I think people will look for this feature.

my $r = rx/ .... /.finalize;  # I wish!

Or, Perl 6 has a much better way to do this sort of thing and I'm just full of old school thinking. Perl 6 has rules instead of regexes. There's actually a parser behind all this. I thought defining a token or rule might be the way to go, but I think I run into the same problem. I don't see a what to have a subrule factory.

Is there some other way I could do this?

like image 386
brian d foy Avatar asked Nov 30 '16 08:11

brian d foy


1 Answers

As an alternative to using a closure, you can of course build the regex via EVAL.

Besides these two arguably subpar solutions, I'm drawing a blank as well. Note that you can do more complex interpolations via the <{...}> syntax, eg

/ <{ BEGIN compute-string-once-at-compile-time }> /

but I don't see how that can be used to solve the problem...

like image 145
Christoph Avatar answered Sep 29 '22 23:09

Christoph