Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

total method and the sigil of a Bag variable in Perl 6

Tags:

set

bag

raku

We can use the total method to know the sum of all the weights in a Bag.

> my $b = (1,2,1).Bag
Bag(1(2), 2)
> $b.total
3

But if we use the % sigil instead of $ for our Bag, we get an error message.

> my %b = (1,2,1).Bag
{1 => 2, 2 => 1}
> %b.total
No such method 'total' for invocant of type 'Hash'. Did you mean 'cotan'?
  in block <unit> at <unknown file> line 1

If %b is explicitly converted to Bag before total, it works:

> %b.Bag.total
3

The question: I used to think that with Set, Bag, SetHash etc., using the % sigil is preferable. Am I wrong?

like image 463
Eugene Barsky Avatar asked May 03 '18 13:05

Eugene Barsky


2 Answers

Bind instead of assign

my %b := (1,2,1).Bag;
say %b.total

Binding (with :=) binds the right hand side directly to the left hand side. In this case a value that does the Associative role gets bound to %b.

Or assign to a Bag

Assigning (with =) assigns (copies) values from the right hand side into the container on the left hand side.

You can assign after first binding to a Bag as follows.

Immediately prior to an assignment a my declarator will bind a suitable container to the declared variable. By default it will be a Hash container if the variable has a % sigil.

But you can specify a variable is bound to some other type of container that's compatible with its sigil:

my %b is Bag = 1,2,1;
say %b.total

With this incantation you need to use = because, by the time that operator is encountered %b has already been bound to a Bag and now you need to assign (copy) into the Bag.

This way you get the simplicity of just providing a list of values (no explicit keys or Bag coercer/constructor necessary) because = is interpreted according to the needs of the container on its left, and a Bag choses to interpret the RHS of = as a list of keys whose occurrence count is what matters to it.

like image 53
raiph Avatar answered Nov 03 '22 23:11

raiph


In Perl 6, assignment to a container can be coercive, that is, it coerces the value to that of the container. See this:

my $b = (1,2,1).Bag;
say $b.^name; # Bag

my %haШ = (1,2,1).Bag;
say  %haШ.^name; # Hash

Binding, on the other hand, binds the type of the container to the contained thing.

So, the answer: you can still use the sigil, but as @raiph said above, use binding so that the Bag or BagHash is not coerced into a simple Hash.

my %real-haШ := (1,2,1).Bag;
say %real-haШ.^name; # Bag
like image 23
jjmerelo Avatar answered Nov 04 '22 00:11

jjmerelo