Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difficulty when constructing a nested data structure

While trying to create a JSON message for an API, I found myself struggling to do something that I thought would be simple. I needed to create a message like the following:

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

However, my first attempt did not work:

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

Trying to simplify things further confused me more:

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

Then I tried to use some temporary variables, and that worked:

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

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

What's going on here?

And is there a way I can achieve my desired output without an extra temporary variable?

like image 830
jja Avatar asked Feb 07 '20 22:02

jja


People also ask

What is a nested data structure?

In data structures, data organizations that are separately identifiable but also part of a larger data organization are said to be nested within the larger organization. A table within a table is a nested table. A list within a list is a nested list.

What is nested data in Python?

In Python, a nested dictionary is a dictionary inside a dictionary. It's a collection of dictionaries into one single dictionary.

What nested data?

Nested data: When data are collected from multiple individuals in a group, the individual data are considered nested within that group. Ordinary least squares (OLS) regression: A statistical model used to describe the relationship between an array of variables (independent variables) and a dependent variable.


Video Answer


1 Answers

You've discovered the single argument rule. Numerous constructs in Raku will iterate the argument they are provided with. This includes the [...] array composer. This is why when we say:

say [1..10];

We get an array that contains 10 elements, not 1. However, it also means that:

say [[1,2]];

Iterates the [1,2], and thus results in [1,2] - as if the inner array were not there. A Hash iterates to its pairs, thus:

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

Actually produces:

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

That is, the array has the pairs. The JSON serializer then serializes each pair as a one-element object.

The solution is to produce a single-element iterable. The infix , operator is what produces lists, so we can use that:

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

Then the single argument to be iterated is a 1-element list with a hash, and you get the result you want.

Easy way to remember it: always use trailing commas when specifying the values of a list, array or hash, even with a single element list, unless you actually are specifying the single iterable from which to populate it.

like image 92
Jonathan Worthington Avatar answered Oct 17 '22 09:10

Jonathan Worthington