Raku Bags

In Perl there’s a common idiom for counting elements: using an hash and autovivification can quickly provide you the number of elements. The idiom is pretty much as follows:

> my @family = <father mother son cat cat dog>;
[father mother son cat cat dog]
> @family.elems
6

> %family-count{ $_ }++ for @family;
Nil
> %family-count.say;
{cat => 2, dog => 1, father => 1, mother => 1, son => 1}



Therefore, asking how many cats live with us? is just a matter of getting a value out of an hash:

> say "There are { %family-count<cat> } cats that live with you";
There are 2 cats that live with you


So far, so good. However, in Raku you have also bags: container that associate to a key and count the number of repetitions. The documentation can be found here.
You can create a new Bag or ask an array to baggify itself:

> my $family-bag = @family.Bag;
Bag(cat(2), dog, father, mother, son)
> say "There are { $family-bag<cat> } cats that live with you";
There are 2 cats that live with you


As you can see, the final result is the same. You can even pass a list of repeated items to create the very same bag:

> $family-bag = Bag.new: <cat cat dog mother father son>;
Bag(cat(2), dog, father, mother, son)


Bags are immutable and therefore you cannot change the values once the Bag has been constructed.
You can however use a BagHash to modify values:

> $family-bag.^name
Bag
> $family-bag<cat>++;
Cannot resolve caller postfix:<++>(Int:D)


> $family-bag = BagHash.new: <cat cat dog mother son father>;
BagHash(cat(2), dog, father, mother, son)
> $family-bag<cat>++;
2
> $family-bag<cat>;
3


The baggy things have interesting methods to get the number of unique elements (~.elems), of total elements (.total) and to get all the element as an array (.roll) and the keys and values:

> my $family-bag = BagHash.new: <cat cat dog mother son father>;
BagHash(cat(2), dog, father, mother, son)

> $family-bag.roll( $family-bag.total );
(son dog son cat cat mother)

> $family-bag.elems
5

> $family-bag.total
6

> $family-bag.keys
(dog father mother son cat)

> $family-bag.values
(1 1 1 1 2)



Conclusion

Bags are a very useful and well done piece of structure to rely on. I just need to get committed in using it!

The article Raku Bags has been posted by Luca Ferrari on September 2, 2020