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.
In reply to Re: (??{ lexical variable })
by jryan
in thread (??{ lexical variable })
by Juerd
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |