Сложность при построении вложенной структуры данных - PullRequest
14 голосов
/ 08 февраля 2020

При попытке создать сообщение JSON для API я обнаружил, что изо всех сил пытаюсь сделать что-то, что, на мой взгляд, будет простым. Мне нужно было создать сообщение вроде следующего:

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

Однако моя первая попытка не сработала:

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

Попытка упростить вещи еще больше смутила меня:

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

Затем я попытался использовать некоторые временные переменные, и это сработало:

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

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

Что здесь происходит?

И есть ли способ добиться желаемого результата без дополнительная временная переменная?

1 Ответ

17 голосов
/ 08 февраля 2020

Вы обнаружили правило с одним аргументом . Многочисленные конструкции в Raku будут повторять аргумент, который им предоставляется. Это включает в себя [...] массив composer. Вот почему, когда мы говорим:

say [1..10];

Мы получаем массив, который содержит 10 элементов, а не 1. Однако это также означает, что:

say [[1,2]];

Итерирует [1,2], и, следовательно, приводит к [1,2] - как будто внутреннего массива там не было. A Hash выполняет итерацию по своим парам, таким образом:

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

Фактически выдает:

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

То есть массив имеет пары. Сериализатор JSON затем сериализует каждую пару как одноэлементный объект.

Решение заключается в создании итерируемого одноэлементного элемента. Оператор infix , - это то, что создает списки, поэтому мы можем использовать это:

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

Тогда единственный аргумент, который нужно перебрать, это список из 1 элемента с ха sh, и вы получите желаемый результат.

Простой способ запомнить его: всегда используйте конечные запятые при указании значений списка, массива или ха sh, даже с одним списком элементов, если вы на самом деле не указываете одну итерацию из которого можно его заполнить.

...