Eu gostaria de fazer uma substituição de string em um for
bloco usando uma captura nomeada. Eu esperava obter os números 1,2,3 como saída. Mas é Nil
para a primeira execução e, em seguida, 1 e 2 para a 2ª e a 3ª execução. Como uso .subst
corretamente a construção do loop? Eu vejo o mesmo comportamento ao usar uma map
construção em vez do for
loop. Funciona como esperado, se eu substituir por um valor fixo de string.
for <a1 b2 c3> -> $var {
say $var;
say $var.subst(/.$<nr>=(\d)/, $<nr>); #.subst(/.$<nr>=(\d)/, 'X'); #OK
}
#`[
This is Rakudo version 2019.11 built on MoarVM version 2019.11
Output:
a1
Use of Nil in string context
in block at test3.pl6 line 3
b2
1
c3
2
]
raku
string-substitution
Valle Lukas
fonte
fonte
S///
algumas vezes. Neste caso, você poderia fazerS[.$<nr>=(\d)] = $<nr> given $var
Respostas:
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 avaliaNil
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 retornaNil
. Então, as coisas já deram errado neste momento, antessubst
mesmo de correr.Depois que Raku reúne essa lista de argumentos, ele tenta chamar
subst
. É bem-sucedido esubst
é 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 passadosubst
.Com a partida na mão, a
subst
seguir , olha o argumento de substituição. Ele encontraNil
e age de acordo.Para a segunda chamada de
subst
,$<nr>
assumiu o valor da primeira chamada desubst
. 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 outrasS
sintaxes válidas, comoS[...] = ...
.)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 ligarsubst
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 congeladoNil
, 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 deCode
(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.fonte