Como iterar através de uma matriz dentro de um hash Raku?


8

Parece uma pergunta simples, mas Perl6 / Raku não está se comportando como eu esperava. Estou tentando criar uma referência a uma matriz dentro de um hash, mas não estou obtendo o comportamento esperado. No Perl5, a resposta envolveria o acesso à matriz por referência, mas não vejo sintaxe equivalente para o 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;

Como obtenho uma nova variável @arr para referenciar a matriz aninhada sem essa camada de índice extra [0] confusa? Isso é um bug ou estou faltando alguma coisa no meu entendimento sobre a manipulação de Raku's Array / ref? Obrigado.

Respostas:


7

Quando você atribui o valor na chave arrà Matriz, @arrele pega o valor em %json{'arr'}que é o Objeto Matriz ["alpha","beta","delta","gamma"]e o coloca para @arrque você obtenha uma Matriz de Matrizes com 1 item.

Você tem algumas opções:

Você pode vincular @arra %json{"arr"}commy @arr := %json{"arr"}

Ou você pode passar %json{"arr"}para uma lista commy (@arr) = %json{"arr"}

Você deve se lembrar de que os objetos Raku Array são.


5
Do ponto de vista do desempenho, a my @arr := %json<arr>solução é a melhor, pois não precisa copiar nenhum valor nem criar objetos adicionais.
Elizabeth Mattijsen

2

Como de costume, depois de escrever + postar minha pergunta, eu respondi minha própria pergunta.

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

Não entendo muito bem por que isso é necessário, mas fornece o comportamento desejado.


3
%json{'arr'}é um escalar (pense, referência a uma matriz). Chamar o método Array é "desreferenciar" o escalar, ou mais exatamente, está colocando o conteúdo dos escalares de seu contêiner escalar em um contêiner de lista. Você também poderia ter escrito %json{'arr'}.flatou |%json{'arr'}, embora eu ache que o Arraymétodo seja um pouco mais rápido nesse caso.
Holli

1
Para elaborar. Em Raku, Matrizes e Listas não se achatam automaticamente, portanto my @a = (1,2), (3,4), criará uma matriz de listas com dois elementos, não uma matriz de entradas com quatro.
Holli

2
Raku não possui referências, possui apenas valores e recipientes imutáveis. Sua solução faz o seguinte: 1. coagir o Arrayobjeto no hash a um Array: isso por si só é um noop, mas o mais importante é que perde o contêiner no qual a matriz foi armazenada no hash. Como o Arrayobjeto é Iterável, ele copiará seus valores para a @arrmatriz, potencialmente fazendo muito trabalho desnecessário para matrizes grandes.
Elizabeth Mattijsen
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.