TL;DR Отложите оценку $<nr>
до завершения оценки регулярного выражения. @JoKing++ предлагает один способ. Другой вариант — просто заключить замену в фигурные скобки ({$<nr>}
).
Что происходит, когда исходный код вызывает subst
Прежде чем Raku попытается вызвать подпрограмму subst
, он составляет список аргументов для передачи ей.
Есть два значения. Первый — это регулярное выражение. Он не запускается. Второе значение $<nr>
. Он оценивается как Nil
, потому что в начале программы текущая переменная объекта сопоставления связана с чем-то, что утверждает, что ее значение равно Nil
, и любая попытка получить доступ к значению ключа в нем — $<nr>
— также возвращает Nil
. Так что к этому моменту все уже пошло не так, еще до того, как subst
запустится.
Как только Raku соберет этот список аргументов, он попытается вызвать subst
. Это удается, и subst
запускается.
Чтобы получить следующее совпадение, subst
запускает регулярное выражение. Это обновляет текущую переменную объекта соответствия $/
. Но уже слишком поздно что-либо менять в значении подстановки, которое уже было передано в subst
.
Имея на руках совпадение, subst
затем просматривает аргумент подстановки. Он находит его Nil
и действует соответственно.
Для второго вызова subst
$<nr>
принимает значение из первого вызова subst
. И так далее.
Два способа отложить оценку $<nr>
@JoKing предлагает рассмотреть возможность использования S///
. Эта конструкция сначала оценивает регулярное выражение (между первой парой /
s), а затем замену (между последней парой /
s). (Тот же принцип применяется, если вы используете другой допустимый синтаксис S
, такой как S[...] = ...
.)
Если вы используете subst
, то, как объяснялось в предыдущем разделе, Raku составляет для него список аргументов перед его вызовом. Он находит регулярное выражение (которое не запускается) и замыкание (которое тоже не запускается). Затем он пытается вызвать subst
с этими аргументами и преуспевает в этом.
Далее запускается subst
. Он получил код как для совпадения (регулярное выражение), так и для замены (замыкание).
Он запускает регулярное выражение как операцию сопоставления. Если регулярное выражение возвращает совпадение, то subst
запускает замыкание и использует возвращаемое значение в качестве подстановки.
Таким образом, поскольку мы перешли от передачи $<nr>
в качестве голого значения, что означало, что оно было заморожено в Nil
, к передаче его в замыкании, которое откладывало его оценку до тех пор, пока $/
не будет установлено в соответствии с заполненной записью <nr>
, мы решили проблему. проблема.
Обратите внимание, что это работает только потому, что тот, кто спроектировал/реализовал subst
, был достаточно умен/хорош, чтобы позволить аргументам соответствия и подстановки быть формами Code
(регулярное выражение для совпадения и обычное закрытие для подстановки), если пользователь этого хочет. Затем сначала выполняется match и только затем выполняется закрытие подстановки, если оно было передано, используя результат этого последнего вызова в качестве окончательного замена. Точно так же работает S///
, потому что это было разработано для оценки замены только после того, как она впервые оценила замену.
person
raiph
schedule
22.01.2020
S///
. В этом случае вы можете сделатьS[.$<nr>=(\d)] = $<nr> given $var
- person Jo King   schedule 30.01.2020