🔬40. Substitution and balanced brackets in Perl 6 regexes

🔬40. Substitution and balanced brackets in Raku regexes

N. B. Perl 6 has been renamed to Raku. Click to read more.


I was randomly looking at different Rakudo Perl 6 source files and found a syntax construction that I could not recognise. I hope you were reading the documentation more carefully (or you did not forget after you have read it) than me, but nevertheless let me devote today’s post to that feature.

So, this was in the src/core/IO/Spec/QNX.pm file:

my class IO::Spec::QNX is IO::Spec::Unix {

    method canonpath ($patharg, :$parent) {
        my $path = $patharg.Str;
        my $node = '';
        if $path ~~ s {^ ( '//' <-[ / ]>+ ) '/'? $} = ''
        or $path ~~ s {^ ( '//' <-[ / ]>+ ) '/' }   = '/'
            { $node = ~ $0; }

        $path = IO::Spec::Unix.canonpath($path, :$parent);

        $node ~ $path;
    }
}

The unusual construction is shown in bold.

The basic form of substitution, which is the same in both Perls, is the following:

my $str = 'Perl 5';
$str ~~ s/5/6/;
say $str;

Delimiters may be different, but unlike Perl 5, you cannot use two pairs of braces:

my $str = 'Perl 5';
$str ~~ s{5}{6};
say $str;

This code generates a compile-time error:

===SORRY!=== Error while compiling /Users/ash/s-2.pl
Unsupported use of brackets around replacement;
in Perl 6 please use assignment syntax
at /Users/ash/s-2.pl:2
------> $str ~~ s{5}⏏{6};

As soon as you use balanced brackets, you are expected to use assignment for the replacement part:

my $str = 'Perl 5';
$str ~~ s{5} = '6';
say $str;

And this is what we see in the original fragment:

if $path ~~ s {^ ( '//' <-[ / ]>+ ) '/'? $} = ''
or $path ~~ s {^ ( '//' <-[ / ]>+ ) '/' } = '/'

By the way, other brackets also work fine, for example:

my $str = 'Perl 5';
$str ~~ s《5》 = '6';
say $str;

You can find the place in the Perl 6 Grammar, where this obsolete syntax bit is caught:

grammar Perl6::Grammar is HLL::Grammar does STD {
    . . .

    # nibbler for s///
    token sibble($l, $lang2, @lang2tweaks?) {
        . . .

        [ <?{ $start ne $stop }>
            <.ws>
            [ <?[ \[ \{ \( \< ]>
            <.obs('brackets around replacement',
                  'assignment syntax')> ]?

It propagates further to the following exception (src/core/Exception.pm):

my class X::Obsolete does X::Comp {
    has $.old;
    has $.replacement; # can't call it $.new, collides with constructor
    has $.when = 'in Perl 6';
    method message() { 
        "??Unsupported use of $.old; $.when please use $.replacement"
    }
}

And that’s all for today. See you tomorrow!

3 thoughts on “🔬40. Substitution and balanced brackets in Perl 6 regexes”

Leave a Reply

Your email address will not be published. Required fields are marked *

Retype the CAPTCHA code from the image
Change the CAPTCHA codeSpeak the CAPTCHA code