¿Cómo itero a través de una matriz dentro de un hash Raku?

8

Esto parece una pregunta simple, pero Perl6 / Raku no se está comportando como esperaba. Estoy tratando de crear una referencia a una matriz dentro de un hash, pero no obtengo el comportamiento esperado. En Perl5, la respuesta implicaría acceder a la matriz por referencia, pero no veo una sintaxis equivalente para Perl6 / Raku.

my $jsonstr = q:to/END/;
{
    "arr" : [
        "alpha","beta","delta","gamma"
    ]
}
END

my %json = from-json $jsonstr;
my @arr = %json{'arr'};
say "Arr length is " ~ @arr.elems; # Expect 4, get 1
say "Orig length is " ~ %json{'arr'}.elems; # Get expected value of 4
say "Arr[0] is " ~@arr[0].^name ~ " of length " ~ @arr[0].elems; # First index is array

say %json{'arr'}[0]; # Indexing into array in original location works as expected
say @arr[0][0]; # But when assigned, it needs an extra index

my @arr2 = @arr[0]; # Same issue in re-assignment here
say "Arr2[0]: " ~ @arr2[0] ~ ", length of " ~ @arr2.elems;

¿Cómo obtengo una nueva variable @arr para hacer referencia a la matriz anidada sin esta capa de índice extra [0] confusa? ¿Es esto un error o me falta algo en mi comprensión del manejo de Raku's Array / ref? Gracias.

Digicrat
fuente

Respuestas:

7

Cuando asigna el valor de la clave arra la matriz @arr, toma el valor en el %json{'arr'}que se encuentra el objeto de matriz ["alpha","beta","delta","gamma"]y lo coloca @arrpara obtener una matriz de matriz con 1 elemento.

Tienes algunas opciones:

Puedes unirte @arra %json{"arr"}conmy @arr := %json{"arr"}

O puede pasar %json{"arr"}a una lista conmy (@arr) = %json{"arr"}

Tienes que recordar en Raku Array's son objetos.

Scimon Proctor
fuente
55
Desde el punto de vista del rendimiento, la my @arr := %json<arr>solución es la mejor, ya que no necesita copiar ningún valor ni crear ningún objeto adicional.
Elizabeth Mattijsen
2

Como de costumbre, después de escribir + publicar mi pregunta, respondí mi propia pregunta.

my @arr = %json{'arr'}.Array;

No entiendo por qué esto es necesario, pero da el comportamiento deseado.

Digicrat
fuente
3
%json{'arr'}es un escalar (piense, referencia a una matriz). Llamar al método Array es "desreferenciar" el escalar, o más exactamente, es poner el contenido escalar de su contenedor escalar en un contenedor de lista. También podría haber escrito %json{'arr'}.flato |%json{'arr'}, aunque creo que el Arraymétodo es un poco más rápido en este caso.
Holli
1
Elaborar. En Raku, las matrices y las listas no se aplanan automáticamente, por lo tanto my @a = (1,2), (3,4), creará una matriz de listas con dos elementos, no una matriz de entradas con cuatro.
Holli
2
Raku no tiene referencias, solo tiene valores y contenedores inmutables. Su solución hace lo siguiente: 1. coaccionar el Arrayobjeto en el hash a an Array: esto en sí mismo es un noop, pero lo más importante es que pierde el contenedor en el que se almacenó la matriz en el hash. Dado que el Arrayobjeto es Iterable, copiará sus valores en la @arrmatriz, lo que posiblemente haga mucho trabajo innecesario para matrices grandes.
Elizabeth Mattijsen