Kesulitan saat membangun struktur data bersarang

14

Saat mencoba membuat pesan JSON untuk API, saya menemukan diri saya berjuang untuk melakukan sesuatu yang saya pikir akan sederhana. Saya perlu membuat pesan seperti berikut:

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

Namun, upaya pertama saya tidak berhasil:

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

Mencoba menyederhanakan banyak hal lebih membingungkan saya:

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

Kemudian saya mencoba menggunakan beberapa variabel sementara, dan itu berhasil:

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

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

Apa yang terjadi di sini?

Dan adakah cara saya dapat mencapai hasil yang diinginkan tanpa variabel sementara tambahan?

jja
sumber
1
say to-json { foo => [ { a => 1 } ] };harus menampilkan sesuatu seperti {"foo":[{"a":1}]}, bukan {"foo":["a":1]}. Yang terakhir adalah salah ketik, kan? Jika tidak, apa say $*PERL.compiler.version;isinya?
raiph
Hm, ya, kamu benar. Saya kira saya salah membaca hal-hal ketika saya mencoba hal-hal. Bahkan say to-json { foo => [ a => 1 ] }keluaran {"foo":[{"a":1}]}jadi siapa yang tahu apa yang saya ketik ketika saya mendapatkannya, jika saya pernah melakukannya. Salahku!
jja

Jawaban:

17

Anda telah menemukan aturan argumen tunggal . Sejumlah konstruksi dalam Raku akan mengulangi argumen yang disediakan. Ini termasuk [...]komposer array. Inilah mengapa ketika kita mengatakan:

say [1..10];

Kami mendapatkan array yang berisi 10 elemen, bukan 1. Namun, itu juga berarti bahwa:

say [[1,2]];

Iterasi [1,2], dan dengan demikian menghasilkan [1,2]- seolah-olah array dalam tidak ada. A Hashberalih ke pasangannya, dengan demikian:

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

Sebenarnya menghasilkan:

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

Artinya, array memiliki pasangan. Serializer JSON kemudian membuat serial setiap pasangan sebagai objek satu elemen.

Solusinya adalah menghasilkan satu elemen yang dapat diubah. ,Operator infiks adalah apa yang menghasilkan daftar, sehingga kami dapat menggunakannya:

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

Maka argumen tunggal yang akan diulang adalah daftar 1-elemen dengan hash, dan Anda mendapatkan hasil yang Anda inginkan.

Cara mudah untuk mengingatnya: selalu gunakan tanda koma saat menentukan nilai dari daftar, array atau hash, bahkan dengan daftar elemen tunggal, kecuali jika Anda benar-benar menentukan iterable tunggal yang digunakan untuk mengisinya.

Jonathan Worthington
sumber
2
Cara lain adalah merinci dalam Skalar: {foo => [$ {a => 1, b => 2}]}
jakar