Can Perl 6 use% sigil for anything other than a hash?

Perl 6 docs on variables note that the % sigil can be used with types that act as Associative . It specifically mentions Pair , Hash, and Map . But how would I get Pair in a variable with % ?

If I use a type constraint, I get a curious error:

 > my Pair %pair = Pair.new( 'a', 'b' ) Type check failed in assignment to %pair; expected Pair but got Str ("b") in block <unit> at <unknown file> line 1 

If I assign without type restriction, I get a hash:

 my %pair = Pair.new: 'a', 'b'; # Hash, not Pair 

Binding:

 my %pair := Pair.new: 'a', 'b'; # Pair 

But if I use a type constraint, I get another curious error:

 > my Pair %p2 := Pair.new: 'a', 'b'; Type check failed in binding; expected Associative[Pair] but got Pair (:a("b")) in block <unit> at <unknown file> line 1 

A similar problem occurs with Bag and Set . Do this with Map and you will get a modified Hash .

Here I see a lot of problems, but perhaps the % sigil is not as universal as they believed me.

+7
perl6 associative
source share
3 answers

You can use % sigiled containers to store any value that the Associative Role does .

You must be careful, as you have discovered, in the way you announce and appoint.

In your example, my Pair %pair you say to make a Hash (not a Pair ) that can contain Pair values ​​( %pair.WHAT = 'Hash[Pair]' )

Try the following:

 my Pair %p2 = mykey => Pair.new: 'a', 'b'; 

which may be enjoyable. By limiting the type of values, you will receive an error message if you say

 %p2<c> = 'd'; 

since you are not assigning a Pair .

Binding, as you have also discovered, works the way you think.

+3
source share

We need to take a few steps back if we want to understand what is happening with your examples:

Variables are tied to objects. By default, sig nal variables are initially bound to assignable container objects ( Scalar for $ and & , Array for @ and Hash for % ).

If you add a type to a variable declaration, for example

 my Int %var 

or equivalent

 my %var of Int 

you place a restriction on the types of values ​​this container may contain.

The assignment variable ( = ) tries to put the value on the right side into a container bound to the variable on the left side, which will fail if this type restriction is not met. By default, only & variables have this limitation (cf (my &).VAR.of vs (my %).VAR.of ).

In contrast, reordering a variable ( := ) will replace the container object. If you want to set restrictions on what types of objects can be connected, you need is instead if of :

 my %var is Pair; %var := x => 1; # ok %var := 42; # not ok 

Sigen variables imply default type restrictions (not for $ , Callable for & , Positional for @ and Associative for % ). Note that this default restriction is overridden explicitly, for example

 my %var is Int; %var := 42; # ok even though 42 is not Associative 

Finally, note that is not only sets a type restriction, but also binds the variable to a newly created instance of this type:

 my %pair is Pair; say %pair; # (Mu) => (Mu), ie Pair.new() 

I do not know how easy it is to make the first one.

+7
source share

Honestly, this seems like a mistake. In containers % there are no problems with Pair storage, which is created using the fat arrow infishing constructor:

 my %pair = what => 'a pair'; 

The container overrides the type, so you get a Hash , not a Pair .

 %pair.WHAT; #=> (Hash) 
+1
source share

All Articles