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 substrotina, 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 Nilporque, no início de um programa, a variável atual do objeto de correspondência está vinculada a algo que afirma que seu valor é Nile 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 substmesmo 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, substexecute 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 substseguir , olha o argumento de substituição. Ele encontra Nile 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 Ssintaxes 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 substcom esses argumentos e consegue fazê-lo.
Em seguida, substcomeç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 substexecutará 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 substfoi 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.