Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I know the following is heinous, & I also fussed with a number of solutions posed in earlier threads about similar questions. Unfortunately, none have worked thus far.

I'm wanting to define a regular expression which will be assigned to a constant, & obviously, I want to determine whether various strings match.

Assigning a pattern to a scalar value works:

#!/usr/bin/perl use strict; use Data::Dumper; my $regex = qr/^(\d{4})-(\d{2})-(\d{2})/; my $s = '2011-02-15'; my ($y, $m, $d) = ($s =~ /$regex/)[0, 1, 2]; print Data::Dumper->Dump([$y, $m, $d], [qw/y m d/]);

However, I'm getting spanked when redefining the pattern as a constant/subroutine (Syntax obviously wrong...):

#!/usr/bin/perl use strict; use Data::Dumper; use constant REGEX => qr/^(\d{4})-(\d{2})-(\d{2})/; my $s = '2011-02-15'; my ($y, $m, $d) = ($s =~ /&{[REGEX]}/)[0, 1, 2]; print Data::Dumper->Dump([$y, $m, $d], [qw/y m d/]);

Any help you can share would be greatly appreciated. I'm using Perl 5.8.8.

Replies are listed 'Best First'.
Re: qr expression defined as constant?
by jwkrahn (Abbot) on Feb 15, 2011 at 23:09 UTC

    Change:

    my ($y, $m, $d) = ($s =~ /&{[REGEX]}/)[0, 1, 2];

    To:

    my ($y, $m, $d) = ($s =~ REGEX)[0, 1, 2];
Re: qr expression defined as constant?
by ELISHEVA (Prior) on Feb 16, 2011 at 07:21 UTC

    The reason constant isn't working for you is that what you get from use constant REGEX ==> is a subroutine: sub REGEX { qr/^(\d{4})-(\d{2})-(\d{2})/ }. In many cases this subroutine call gets reduced to a constant by the Perl optimizer. However, this happens after the parsing stage so constants declared with use constant can only be used in places where you could use a subroutine call.

    Although you can use subroutine calls in the second half of a substitution regex (using the e or ee modifier), this is not so for the matching portion. Whether in substitutions or straight matching, the matching portion of a Perl regular expressions normally only allow the insertion of variables, not subroutine calls.

    There is however an experimental feature (present since 5.8.8 but still in 5.12) that will allow expressions, including subroutine calls, to be evaluated in the matching portion: (??:{ expr }). Thus this works with a constant:

    use constant REGEX => qr/^(\d{4})-(\d{2})-(\d{2})/; while (<>) { chomp; printf "$_: match=%s\n", ($_ =~ m{(??{REGEX})} ? 1 : 0); }

    For more information on (??:{code}) check perlre.

    As for using Readonly, it is a judgment call: the benefits of read-only-ness vs. performance/distribution issues. There are two versions of that module, a pure Perl implementation that uses tied variables and another that uses an XS module. The pure Perl implementation is significantly slower than a plain variable or a subroutine call. The XS version requires a compiler on your machine and any machine to which you distribute. For more discussion about trade-offs, see the the CONS section of the Readonly documentation.

Re: qr expression defined as constant?
by wind (Priest) on Feb 15, 2011 at 23:40 UTC
Re: qr expression defined as constant?
by ikegami (Patriarch) on Feb 16, 2011 at 15:38 UTC

    Those square brackets are the array constructor operator. Nothing to do with regex patterns.

    my @anon = REGEX; my $anon = \@anon; /&$anon/

    should be

    my @anon = REGEX; my $anon = \@anon; /@$anon/

    so

    /&{[ REGEX ]}/

    should be

    /@{[ REGEX ]}/