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 (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-)