İç içe veri yapısı oluştururken zorluk


14

Bir API için JSON mesajı oluşturmaya çalışırken kendimi basit olacağını düşündüğüm bir şey yapmakta zorlandım. Aşağıdaki gibi bir mesaj oluşturmak gerekiyordu:

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

Ancak, ilk denemem işe yaramadı:

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

İşleri basitleştirmeye çalışmak beni daha çok şaşırttı:

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

Sonra bazı geçici değişkenleri kullanmaya çalıştım ve işe yaradı:

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

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

Burada neler oluyor?

Ekstra geçici değişken olmadan istediğim çıktıyı elde edebilmemin bir yolu var mı?


1
say to-json { foo => [ { a => 1 } ] };gibi bir şey çıkarmalı {"foo":[{"a":1}]}, değil {"foo":["a":1]}. İkincisi bir yazım hatası değil mi? Değilse, ne say $*PERL.compiler.version;diyor?
raiph

Hm, evet, haklısın. Sanırım bir şeyler denerken bir şeyleri yanlış okudum. say to-json { foo => [ a => 1 ] }Çıktılar bile, {"foo":[{"a":1}]}bunu aldığımda ne yazdığımı kim bilebilir ki, eğer yaparsam. Benim hatam!
jja

Yanıtlar:


17

Tek argüman kuralını keşfettiniz . Raku'daki çok sayıda yapı kendilerine sunulan argümanı yineleyecektir. Bu [...]dizi bestecisini içerir . Bu yüzden dediğimizde:

say [1..10];

1 değil, 10 öğe içeren bir dizi alırız. Bununla birlikte, aynı zamanda şu anlama gelir:

say [[1,2]];

İç diziyi orada değilmiş gibi yineleyerek [1,2]sonuçlanır [1,2]. A Hash, çiftlerine yinelenir, böylece:

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

Aslında üretir:

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

Yani, dizinin çiftleri vardır. JSON serileştiricisi daha sonra her bir çifti tek elemanlı bir nesne olarak serileştirir.

Çözüm, tek elemanlı bir yinelenebilir üretmektir. Infix ,operatörü liste üreten şeydir, bu yüzden bunu kullanabiliriz:

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

Daha sonra yinelenecek tek argüman, karma içeren 1 öğeli bir listedir ve istediğiniz sonucu elde edersiniz.

Hatırlamanın kolay yolu: Bir listenin, dizinin veya karmanın değerlerini belirtirken, gerçekte onu dolduracağınız tek bir yinelemeyi belirtmediğiniz sürece, tek bir öğe listesiyle bile her zaman izleyen virgül kullanın.


2
Diğer bir yol ise bir Skaler'de öğe oluşturmaktır: {foo => [$ {a => 1, b => 2}]}
jakar
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.