8
votes

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?

1
The "close over a copy" solution doesn't look as clunky if you factor it out as a subroutine that accepts the variable fields as parameters. I've used that solution in some of my own Perl 6 code. I don't think there's currently a better way to do it.smls
I know this is not what you're asking, but variables do in fact interpolate in Perl6 regexes, but they're treated as literal strings, not sub-regexes. In your example, you could use rx/$n/ or maybe better rx/"$n"/ and get the same results. (Including the same matched/missed behaviour.)mscha
You're looking at the wrong dimension. I want the current value of the variable, not the later value. Not even the examples you give do that.brian d foy
@briandfoy Could you please explain, what's the point of using rx/ ( <$n> ) /, not simply rx/ $n /?Eugene Barsky

1 Answers

6
votes

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...