i've got a function, into which i want to be able to pass a list of lists, like in this artificial example:
sub print_lists(@input) {
.say for @input
}
my @list_of_two_lists = ((1, 2), (3, 4));
print_lists(@list_of_two_lists);
this gives the following output, as expected:
(1, 2)
(3, 4)
but if i do this:
my @list_of_one_list = ((1, 2));
print_lists(@list_of_one_list);
i get this output:
1
2
i.e. it flattens the list containing one list of two elements, into a single list of two elements.
what am i doing wrong? what do i need to do if i want to be able to pass in a list containing a single list?
Individual elements can be pulled out of a list using a subscript. The first element of a list is at index number zero: Variables in Raku whose names bear the @ sigil are expected to contain some sort of list-like object. Of course, other variables may also contain these objects, but @ -sigiled variables always do, and are expected to act the part.
These are called sequences, which are of type Seq. As it so happens, loops return Seq s. So, it is fine to have infinite lists in Raku, just so long as you never ask them for all their elements.
This is actually one of the trickiest parts of Raku list handling to get a firm understanding of. First, be aware that because itemization in Arrays is assumed, it essentially means that $ (…) s are being put around everything that you assign to an array, if you do not put them there yourself.
Raku will automatically type-check values and create Scalars to contain them when Arrays are initialized, assigned to, or constructed. This is actually one of the trickiest parts of Raku list handling to get a firm understanding of.
This behavior is a consequence of two Raku features, both of which are worth knowing.
The first is the Single Argument Rule. It's important enough to be worth reading the docs on, but the key takeaway is that when you pass a single list (as you do in with @list_of_one_list
) constructs like for
will iterate over each item in the list rather than over the list as a single item. In this case, that means iterating over the two items in the list, 1
, and 2
.
At this point, you might be thinking "but @list_of_one_list
didn't have two items in it – it had one item: the list (1, 2)
". But that's because we haven't gotten to the second point to understand: In Raku (
and )
are not what makes something a list. Instead, using the ,
operator is what constructs a list. This can take a tad bit of getting used to, but it's what allows Raku to treat parentheses as optional in many places that other languages require them.
To see this second point in action, I suggest you check out how .raku
prints out your @list_of_lists
. Compare:
my @list_of_one_list = ((1, 2));
say @list_of_one_list; # OUTPUT: «[1, 2]»
my @list-of-one-list = (1, 2),;
say @list-of-one-list; # OUTPUT: «[(1, 2)]»
And that's all the info you need to answer your question: simply add a ,
when you build your list of one list.
I hope that helped :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With