Podczas próby utworzenia komunikatu JSON dla interfejsu API miałem trudności z zrobieniem czegoś, co moim zdaniem byłoby proste. Musiałem utworzyć wiadomość podobną do następującej:
{ "list": [ { "foo": 1, "bar": 2 } ] }
Jednak moja pierwsza próba nie zadziałała:
say to-json { foo => [ { a => 1, b => 2 } ] };
# {"foo":[{"a":1},{"b":2}]}
Próba dalszego uproszczenia sprawiła mi więcej zamieszania:
say { foo => [ { a => 1 } ] };
# {foo => [a => 1]}
# Note that this is not JSON, but I expected to see curly braces
Potem spróbowałem użyć zmiennych tymczasowych i to zadziałało:
my @list = { a => 1 };
say to-json { foo => @list };
# {"foo":[{"a":1}]}
my %hash = ( a => 1 );
say to-json { foo => [ %hash ] };
# {"foo":[{"a":1}]}
Co tu się dzieje?
I czy jest sposób, w jaki mogę osiągnąć pożądaną wydajność bez dodatkowej zmiennej tymczasowej?
say to-json { foo => [ { a => 1 } ] };
powinien wypisać coś takiego{"foo":[{"a":1}]}
, a nie{"foo":["a":1]}
. Ten ostatni to literówka, prawda? Jeśli nie, cosay $*PERL.compiler.version;
powiesz?say to-json { foo => [ a => 1 ] }
wyjściowe,{"foo":[{"a":1}]}
więc kto wie, co napisałem, kiedy to dostałem, jeśli kiedykolwiek to zrobiłem. Mój błąd!Odpowiedzi:
Pan odkrył zasadę jeden argument . Liczne konstrukcje w Raku będą iterować argument, którym je dostarczono. Obejmuje to
[...]
kompozytora tablicowego. Właśnie dlatego, gdy mówimy:Otrzymujemy tablicę zawierającą 10 elementów, a nie 1. Oznacza to jednak, że:
Iteruje
[1,2]
, a zatem skutkuje[1,2]
- tak jakby nie było tablicy wewnętrznej.Hash
Iteracje swoich par, a więc:Faktycznie produkuje:
Oznacza to, że tablica ma pary. Serializator JSON serializuje następnie każdą parę jako obiekt jednoelementowy.
Rozwiązaniem jest utworzenie iterowalnego elementu.
,
Operator infix tworzy listy, więc możemy użyć tego:Wówczas jedynym argumentem, który ma być iterowany, jest lista 1-elementowa z skrótem i otrzymujesz pożądany wynik.
Łatwy sposób na zapamiętanie: zawsze używaj przecinków końcowych przy określaniu wartości listy, tablicy lub skrótu, nawet z listą pojedynczych elementów, chyba że tak naprawdę określasz pojedynczy iterowalny element, z którego chcesz ją wypełnić.
źródło