http://www.perlmonks.org?node_id=129266

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

Is it possible to use a `named constant’ in a regex’s quantifiers?

I want to restrict the value of `word length’ to being stored in just the one place and so, using constant.pm (as described in Perl Debugged by Peter Scott and Ed Wright) I’ve come up with the following

#!/usr/local/perl/bin/perl use strict; use warnings; use constant WORD_LENGTH => 9; # define constant value in one plac +e my $Word_Length = WORD_LENGTH; # mmm, is this the best I can do? my $target_letters = 'x'; while ( $target_letters !~ /^[a-z]{$Word_Length}$/i ) { print "Enter the " . WORD_LENGTH . " letters for today\n"; $target_letters = <STDIN>; print "$target_letters\n"; } …

… which works fine, but requires the extra $Word_Length variable that, something tells me, a good Perlophone would eschew 8-)

I'm aware (Perl Debugged again) that the `name constant' is constructed as a subroutine when it's defined, and returns its value when it's called. So I've tried  ...{WORD_LENGTH()} based on `if it looks like a function, it is a function'. I also tried ...{&WORD_LENGTH} both with and without `()'s.

Monks advice keenly sought… /hagen

Replies are listed 'Best First'.
Re: subroutine within regex quantifier?
by chromatic (Archbishop) on Dec 04, 2001 at 09:39 UTC
    There's the experimental (?{...}) construct, but I can't think of a way to use that. Why not use length and a slightly different regex?
    while (length($target_letters) != WORD_LENGTH && $target_letters =~ /[^A-Za-z]/) { # prompt }
    Seems clearer to me, as well as *possible*.

      Thanks chromatic, that is clearer and `feels' more Perl-like. I got fixated on having to use the quantifier.

      .

      I also appreciate dws's suggestion re compiling only once.

      Thanks for the prompt responses

      hagen 8-)
Re: subroutine within regex quantifier?
by chipmunk (Parson) on Dec 04, 2001 at 09:54 UTC
    Subroutines and method calls don't interpolate inside strings or regexes. However, there's a common trick for interpolating an arbitrary expression inside a double-quoted string, that will work just as well in a regex:
    "@{[ reverse 1 .. 3 ]} go!" # reverse 1 .. 10 is in list context "2 + 2 = ${\( 2 + 2 )}"; # 2 + 2 is in scalar context
    So, you could write your regex in one of these ways:
    /^[a-z]{@{[ WORD_LENGTH ]}}$/i /^[a-z]{${ \WORD_LENGTH }}$/i
    Although they might be hard to read... :)
Re: subroutine within regex quantifier?
by dws (Chancellor) on Dec 04, 2001 at 09:36 UTC
    while ( $target_letters !~ /^[a-z]{$Word_Length}$/i ) { ...
    Whether you find a way to use WORD_LENGTH directly or not, you might wish to ensure that the regex is compiled exactly once. /o is your friend.

Re: subroutine within regex quantifier?
by hagen (Friar) on Dec 04, 2001 at 10:52 UTC

    Just a bit of (probably excessive) detail...
    In order to get the WORD_LENGTH letters as letters,
    OR to prompt if I didn't get them, I needed:

    while (length($target_letters) != WORD_LENGTH || $target_letters !~ /[^A-Za-z]/) { # prompt } process the word

    That is, I changed the && to || and reversed the match to !~, now it works like a bought one.

    Thanks chipmunk for your suggestions... I'm a bit
    of a newbie, and will need to read up on the syntax there.

    I know (a little) about array and hash references, including (even littler)
    about anonymous ones but I'd been `saving' myself from subroutine refs,
    as they make my head hurt a bit at this stage of my vocation 8-)

    hagen