Difficoltà nella costruzione di una struttura dati nidificata


14

Durante il tentativo di creare un messaggio JSON per un'API, mi sono trovato a lottare per fare qualcosa che pensavo fosse semplice. Avevo bisogno di creare un messaggio come il seguente:

{ "list": [ { "foo": 1, "bar": 2 } ] }

Tuttavia, il mio primo tentativo non ha funzionato:

say to-json { foo => [ { a => 1, b => 2 } ] };
# {"foo":[{"a":1},{"b":2}]}

Cercare di semplificare le cose mi ha ulteriormente confuso:

say { foo => [ { a => 1 } ] };
# {foo => [a => 1]}
# Note that this is not JSON, but I expected to see curly braces

Quindi ho provato ad usare alcune variabili temporanee e ha funzionato:

my @list = { a => 1 };
say to-json { foo => @list };
# {"foo":[{"a":1}]}

my %hash = ( a => 1 );
say to-json { foo => [ %hash ] };
# {"foo":[{"a":1}]}

Cosa sta succedendo qui?

E c'è un modo per ottenere l'output desiderato senza una variabile temporanea aggiuntiva?


1
say to-json { foo => [ { a => 1 } ] };dovrebbe produrre qualcosa di simile {"foo":[{"a":1}]}, no {"foo":["a":1]}. Quest'ultimo è un errore di battitura, giusto? In caso contrario, cosa say $*PERL.compiler.version;dice?
Raiph

Hm, si, hai ragione. Immagino di aver letto male le cose quando stavo provando cose. Anche le say to-json { foo => [ a => 1 ] }uscite, {"foo":[{"a":1}]}quindi chissà cosa ho digitato quando l'ho ottenuto, se mai l'ho fatto. Colpa mia!
jja

Risposte:


17

Hai scoperto la regola dell'argomento singolo . Numerosi costrutti in Raku ripeteranno l'argomento con cui sono forniti. Ciò include il [...]compositore di array. Questo è il motivo per cui quando diciamo:

say [1..10];

Otteniamo un array che contiene 10 elementi, non 1. Tuttavia, significa anche che:

say [[1,2]];

Itera il [1,2], e quindi risulta [1,2]- come se l'array interno non fosse presente. A Hashscorre le sue coppie, quindi:

{ foo => [ { a => 1, b => 2 } ] }

Produce attualmente:

{ foo => [ a => 1, b => 2 ] }

Cioè, l'array ha le coppie. Il serializzatore JSON quindi serializza ogni coppia come un oggetto a un elemento.

La soluzione è produrre un iterable a singolo elemento. L' ,operatore infix è ciò che produce elenchi, quindi possiamo usare quello:

say to-json { foo => [ { a => 1, b => 2 }, ] };
#                        note the , here ^

Quindi il singolo argomento da ripetere è un elenco di 1 elemento con un hash e ottieni il risultato che desideri.

Modo semplice per ricordarlo: utilizzare sempre virgole finali quando si specificano i valori di un elenco, array o hash, anche con un singolo elenco di elementi, a meno che non si stia specificando il singolo iterabile da cui popolarlo.


2
L'altro modo è dettagliare in uno scalare: {foo => [$ {a => 1, b => 2}]}
jakar il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.