A new JAPH

http://perl-blog.abigail.be/post/9347752138/a-new-japh

Somewhere between "use re 'eval'" and "no re 'eval'"

Say, you have a function, which takes a string, a pattern, and then matches the pattern to the string, but with a twist; a (fixed) code fragment is inserted:

sub example {
    my ($str, $pattern) = @_;
    $str =~ /$pattern(?{ 1; })/;
}

The code block here is trivial, because it's not about the content of the block, just about its existence.

The above doesn't work, because by default you cannot interpolate a string in a pattern containing code blocks. So, you have to use re 'eval';:

sub example {
    my ($str, $pattern) = @_;
    use re 'eval';
    $str =~ /$pattern(?{ 1; })/;
}

Now, that works, but that works a bit too well for my liking - it would now run code blocks if they are passed in using $pattern. This is not what I want. The following seems to fix that:

sub example {
    my ($str, $pattern) = @_;
    no re 'eval';
    $pattern = qr /$pattern/;
    use re 'eval';
    $str =~ /$pattern(?{ 1; })/;
}

This dies if $pattern contains a (?{ code }) block. Except that it doesn't die when $pattern is already a compiled pattern - that's deemed safe. So, we need an additional stringification:

sub example {
    my ($str, $pattern) = @_;   
    no re 'eval';
    $pattern = "$pattern";
    $pattern = qr /$pattern/;
    use re 'eval';
    $str =~ /$pattern(?{ 1; })/;
}

This does what I want it to do: run the code block, but die if $pattern contains a code block, regardless whether it's passed as a string or a compiled regexp.

But I wonder, is there a less cluncky way?