Как оператор qr/STRING/в Perl решает, нужно ли компилировать STRING?

docs для qr/STRING/ скажите:

Этот оператор цитирует (и, возможно, компилирует) его STRING как регулярное выражение.

Меня беспокоит роль в круглых скобках. Я не могу думать о каких-либо случаях, когда я не хочу, чтобы он компилировал регулярное выражение из STRING. Является ли это в скобках утверждение только ласковыми словами, чтобы охватить какой-либо будущий случай, когда компиляция не нужна или есть ли сегодняшний случай (или в более ранней версии Perl), где STRING не будет скомпилирован?

Ответы

Ответ 1

"Возможно, компилирует" часть документации, вероятно, относится к ситуациям, подобным приведенным ниже, где аргумент qr// является уже скомпилированным регулярным выражением:

use re 'debug';

$re1 = qr/foo/;
$re2 = qr/$re1/;

Запуск этой программы показывает только одно компилируемое регулярное выражение.

Независимо от намерений этого прохода, лукавые намеки на внутренние детали не дают четкой документации. Я думаю, что патч doc был бы полезен.

Ответ 2

Изменить: этот ответ неправильный (или, по крайней мере, ошибочный), но есть интересные обсуждения в комментариях, которые стоит сохранить. Ответ на вопрос Сиракузы, кажется, на правильном пути.


В документации для qr// указано, что

STRING интерполируется так же, как и PATTERN в m/PATTERN/.

который предположительно включает в себя поведение не перекомпилированных регулярных выражений, для которых шаблон не изменился, или не может измениться в случае отсутствия интерполированных переменных. Например, вам не нужно перекомпилировать этот шаблон на каждой итерации цикла:

foreach my $char ('a' .. 'z') {
    my $vowel = qr/[aeiou]/;
    say "$char is a vowel" if $char =~ $vowel;
}

Ответ 3

Если регулярное выражение содержит любые интерполированные строки, оно всегда компилируется (возможно, нет, если вы используете переключатель /o - я признаюсь /o всегда меня путал). Если регулярное выражение содержит только буквальный текст, я верю, что ответ Адама правильный.

IIRC он предназначен для обработки этого сценария:

while (my $foo = $something->next) {
     my $regex1 = qr/ab(cd+)ef?/; # only compiled once
     my $regex2 = qr/ab${foo}*ef/; # compiled every time through the loop
     # do stuff with $regex1 and $regex2
}