in reply to (??{ lexical variable })

The solution becomes clear when one realizes that qr// regexes are nothing but strings (albiet special string), and that they are not interpolated until runtime. Consider:

my $inlinetag = do { my $acc = qr/(?> \{ (?: (?> \\. | [^\\{}]+ | (??{ $acc }) ) )* + \} )/x; qr/ \{ (\w+): ( (?: (?> \\. | [^\\{}]+ | (??{ $acc }) ) )* +) \} /x; };

In this modified snippet, the $acc regex is constructed, and scoped lexically to the do block. Next, the unnamed regex is constructed. Note that both of these pass strict checking since $acc was created in the same block, and thus exists. Since the second regex was the last statement in the do block, it is returned, and is assigned to $inlinetag. I believe this is the behavior you expected.

So what is the problem? The problem is that when $inlinetag is expanded at runtime, $acc no longer exists since it went out of scope when the do block returned the unnamed regex and assigned it to $inlinetag. A potential solution is just to get rid of the do block:

my $acc = qr/(?> \{ (?: (?> \\. | [^\\{}]+ | (??{ $acc }) ) )* + \} )/x; my $inlinetag = qr/ \{ (\w+): ( (?: (?> \\. | [^\\{}]+ | (??{ $acc }) ) )* +) \} /x;

Or, if you're really worried about cluttering your namespace, you can do some closure magic:

my $inlinetag = sub { my $acc = qr/(?> \{ (?: (?> \\. | [^\\{}]+ | (??{ $acc }) ) )* + \} )/x; qr/ \{ (\w+): ( (?: (?> \\. | [^\\{}]+ | (??{ $acc }) ) )* +) \} /x; };

However, you must now use it like this: qr/(??{$inlinetag->()}/ rather than like qr/$inlinetag/ with the first method.

Replies are listed 'Best First'.
Re: Re: (??{ lexical variable })
by Juerd (Abbot) on Dec 03, 2002 at 14:45 UTC

    Wonderful explanation. Thanks!

    - Yes, I reinvent wheels.
    - Spam: Visit eurotraQ.