Me gustaría hacer una sustitución de cadena en un for
bloque usando una captura con nombre. Esperaba obtener los números 1,2,3 como salida. Pero es Nil
para la primera carrera, y luego 1 y 2 para la segunda y tercera carrera. ¿Cómo uso .subst
correctamente en la construcción de bucle? Veo el mismo comportamiento cuando uso una map
construcción en lugar del for
bucle. Funciona como se esperaba, si lo reemplazo con un valor de cadena fijo.
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
fuente
fuente
S///
veces. En este caso, podrías hacerloS[.$<nr>=(\d)] = $<nr> given $var
Respuestas:
TL; DR Aplazar la evaluación
$<nr>
hasta después de la evaluación de la expresión regular. @ JoKing ++ sugiere una forma . Otra es simplemente envolver el reemplazo con llaves ({$<nr>}
).¿Qué sucede cuando su código original llama?
subst
Antes de que Raku intente llamar a la
subst
rutina, reúne una lista de argumentos para pasarle.Hay dos valores El primero es una expresión regular. No , no funciona . El segundo valor es
$<nr>
. Se evalúaNil
porque, al comienzo de un programa, la variable de objeto de coincidencia actual está vinculada a algo que afirma que su valor esNil
y cualquier intento de acceder al valor de una clave dentro de él$<nr>
- también devuelveNil
. Entonces, las cosas ya han salido mal en este punto, antes desubst
que se ejecute.Una vez que Raku ha reunido esta lista de argumentos, intenta llamar
subst
. Tiene éxito ysubst
corre.Para obtener el próximo partido,
subst
ejecuta la expresión regular. Esto actualiza la variable de objeto de coincidencia actual$/
. Pero es demasiado tarde para hacer alguna diferencia en el valor de sustitución al que ya se ha pasadosubst
.Con una coincidencia en la mano,
subst
luego mira el argumento de sustitución. Lo encuentraNil
y actúa en consecuencia.Para la segunda llamada de
subst
,$<nr>
ha tomado el valor de la primera llamada desubst
. Y así.Dos formas de diferir la evaluación de
$<nr>
@JoKing sugiere considerar el uso de
S///
. Esta construcción evalúa primero la expresión regular (entre el primer par de/
s), luego el reemplazo (entre el último par de/
s). (El mismo principio se aplica si utiliza otrasS
sintaxis válidas comoS[...] = ...
).Si usa
subst
, entonces, como se explicó en la sección anterior, Raku reúne la lista de argumentos antes de llamarlo. Encuentra una expresión regular (que no se ejecuta) y un cierre (que tampoco se ejecuta). Luego intenta llamarsubst
con esos argumentos y logra hacerlo.A continuación,
subst
comienza a correr. Ha recibido código tanto para el partido (una expresión regular) como para la sustitución (un cierre).Ejecuta la expresión regular como la operación de coincidencia. Si la expresión regular devuelve una coincidencia,
subst
ejecuta el cierre y utiliza el valor que devuelve como la sustitución.Por lo tanto, debido a que cambiamos de pasar
$<nr>
como un valor desnudo, lo que significaba que se congelabaNil
, a pasarlo envuelto en un cierre, lo que aplazó su evaluación hasta que$/
se ajustara a una coincidencia con una<nr>
entrada poblada , resolvimos el problema.Tenga en cuenta que esto solo funciona porque quien diseñó / implementó
subst
fue lo suficientemente inteligente / amable como para permitir que los argumentos de coincidencia y sustitución sean formas deCode
(una expresión regular para la coincidencia y el cierre ordinario para la sustitución) si un usuario lo desea. Luego ejecuta el partido primero y solo luego ejecuta el cierre de sustitución si se ha pasado uno, utilizando el resultado de esa última llamada como la sustitución final. Del mismo modo,S///
funciona porque eso ha sido diseñado para evaluar solo el reemplazo después de que primero se evaluó la sustitución.fuente