проверить регулярное выражение с переменной - PullRequest
7 голосов
/ 10 февраля 2020
sub make-regex {
    my $what's-in-the-box = rand > .5 ?? 'x' !! 'y';
    /$what's-in-the-box/
}

my $lol-who-knows = make-regex;
$lol-who-knows.gist.say;

Как вы видите внутренности регулярного выражения (то есть x или y)? Принудительное совпадение не является решением.

1 Ответ

6 голосов
/ 10 февраля 2020

Как вы видите внутренности регулярного выражения (то есть x или y)?

Вы:

  • Статически скомпилируйте регулярное выражение Для этого потребуется использовать компилятор raku, то есть Rakudo.

  • Динамически вычислять регулярное выражение, чтобы переменная $what's-in-the-box в вашем регулярном выражении интерполировалась и превращалась в x или y. Для этого потребуется запустить регулярное выражение в виде кода. Это, в свою очередь, означает как использование Rakudo, так и запуск регулярного выражения с Match объектным инвокантом (или экземпляром подкласса или, возможно, фиктивным объектом эквивалентом).

  • Просмотр полученного регулярного выражения. Для этого потребуется использовать набор инструментов (Rakudo), определяющий c функциональность самоанализа или отладки.

Принудительное совпадение не является решением.

Вы можете запустить регулярное выражение без ввода, если ваша задача - просто избежать успешного совпадения:

say Match.new.&$lol-who-knows; # #<failed match>

Но оно должно быть запущено, в противном случае переменная $what's-in-the-box не превратится в x или y. Вы можете подумать, что можете обмануть это, написав что-то, имитирующее эту часть конструкции / использования reku regex, но есть веская причина думать, что это не сработает [1] .

И затем вы должны просмотреть его внутренности, используя возможности цепочки инструментов Rakudo, после того, как вы запустили его и до его завершения.

Регулярное выражение - это метод

В raku, Regex - это код, подкласс Method.

Пока вы не запустите его, используя его в совпадении, этот код будет просто /$what's-in-the-box/ (иначе regex { $what's-in-the-box }). Это эквивалентно примерно так:

method {
  ...self should be a Match or a sub-class of it
  ...if self is not an instance, create a new one
  ...do matching -- compiler evaluates $what's-in-the-box during this
  ...return updated self / new instance
}

(Чтобы увидеть немного более подробно, см. ответ Морица на SO Могу ли я изменить сленг внутри метода? .)

Процедура - это замыкание

Вы создаете свое регулярное выражение внутри замыкания с именем make-regex. Компилятор определяет, что вы использовали $what's-in-the-box, и, следовательно, зависает от переменной даже после возврата закрытия make-regex. Позже, если / когда ваше регулярное выражение равно run , переменная $what's-in-the-box будет заменена значением в тот момент, когда регулярное выражение выполнено .

Сноски

[1] Есть множество огромных сложностей, с которыми вы столкнетесь, если попытаетесь выполнить обход с использованием компилятора. Даже что-то простое, например, интерполяция, нетривиально. Цитируя Джонатана Уортингтона, в 2020 году :

Я подумал: о, я только строю [инструмент, который] не настоящий компилятор. Я могу ... иметь более простую модель разрешения символов. В конце концов оказалось, что нет, я не мог на самом деле. Это начало создавать нам некоторые проблемы. Когда мы выровняли способ разрешения символов с помощью тех же алгоритмов и структур поиска, которые использовались в компиляторе, вдруг все стало намного проще.

...