DR; TL avaliação Defer de $<nr>
até após a avaliação da expressão regular. @ JoKing ++ sugere uma maneira . Outra é apenas envolver a substituição com chaves ( {$<nr>}
).
O que acontece quando o código original chama subst
Antes de Raku tentar chamar a subst
rotina, ele reúne uma lista de argumentos a serem transmitidos.
Existem dois valores. O primeiro é um regex. Ele não executar . O segundo valor é $<nr>
. Ele avalia Nil
porque, no início de um programa, a variável atual do objeto de correspondência está vinculada a algo que afirma que seu valor é Nil
e qualquer tentativa de acessar o valor de uma chave dentro dele - $<nr>
- também retorna Nil
. Então, as coisas já deram errado neste momento, antes subst
mesmo de correr.
Depois que Raku reúne essa lista de argumentos, ele tenta chamar subst
. É bem-sucedido e subst
é executado.
Para obter a próxima partida, subst
execute o regex. Isso atualiza a variável atual do objeto de correspondência $/
. Mas é tarde demais para fazer alguma diferença no valor de substituição que já foi passado subst
.
Com a partida na mão, a subst
seguir , olha o argumento de substituição. Ele encontra Nil
e age de acordo.
Para a segunda chamada de subst
, $<nr>
assumiu o valor da primeira chamada de subst
. E assim por diante.
Duas maneiras de adiar a avaliação de $<nr>
@JoKing sugere considerar o uso de S///
. Essa construção avalia primeiro o regex (entre o primeiro par de /
s) e depois a substituição (entre o último par de /
s). (O mesmo princípio se aplica se você usar outras S
sintaxes válidas, como S[...] = ...
.)
Se você usar subst
, então, como explicado na seção anterior, Raku reúne a lista de argumentos antes de chamá-lo. Ele encontra uma regex (que não é executada) e um fechamento (que também não é executado). Em seguida, tenta ligar subst
com esses argumentos e consegue fazê-lo.
Em seguida, subst
começa a correr. Ele recebeu código para a partida (uma regex) e a substituição (um fechamento).
Ele executa a regex como a operação correspondente. Se o regex retornar uma correspondência, ele subst
executará o fechamento e usará o valor que ele retornará como substituição.
Assim, como passamos de passar $<nr>
como um valor nu, o que significava que ele estava congelado Nil
, para passá-lo embrulhado em um fechamento, que adiou sua avaliação até $/
que fosse definido como uma correspondência com uma <nr>
entrada preenchida , resolvemos o problema.
Observe que isso só funciona porque quem projetou / implementou subst
foi inteligente / agradável o suficiente para permitir que os argumentos de correspondência e substituição sejam formas de Code
(uma regex para a correspondência e fechamento comum para a substituição) se um usuário desejar. Em seguida, ele executa a partida primeiro e só então executa o fechamento da substituição se tiver sido aprovada uma, usando o resultado dessa última chamada como a substituição final. Da mesma forma, S///
funciona porque que foi concebido apenas para avaliar a substituição após ser avaliadas primeiro a substituição.