Is it Perl 6 Hash or Block?

This is a bit of an unexpected behavior that can bite newbies. First, is it intended? Secondly, what else does Perl 6 use to guess which object to create? He starts by thinking that it is Block or Hash, and then changes, or decides at the end?

You can create a hash with curly braces and a bold arrow:

my $color-name-to-rgb = { 'red' => 'FF0000', }; put $color-name-to-rgb.^name; # Hash 

Using a different pair of notations also creates a hash .

 my $color-name-to-rgb = { :red('FF0000'), }; 

But, in the absence of a bold arrow, I get a block instead:

 my $color-name-to-rgb = { 'red', 'FF0000', }; put $color-name-to-rgb.^name; # Block 

The hash docs only mention that using $_ inside curly braces creates a block .

There are other ways to determine the hash, but I'm asking about this specific syntax and not looking for workarounds that I already know about.

 $ perl6 -v This is Rakudo version 2017.04.3 built on MoarVM version 2017.04-53-g66c6dda implementing Perl 6.c. 
+9
block perl6 hash
source share
2 answers

Perl6's preferred method is to use %( ) to create hashes.

 my $color-name-to-rgb = %( 'red', 'FF0000', ); 

I would not recommend that people use curly braces to create hashes. If they want to make a hash, then %( ) is the right way to do this.

If you came from the world of Perl 5, it is best to use %( ) instead of { } when creating a hash.

+11
source share

TL; DR This answer starts with the simplest description that I think is reasonable, and then tries to cover everything in detail. Please let me know in the comments if something is too complicated or missing.

This rule applies only to the position term.

Only code with brackets ( {...} ) in term 1 obeys this DWIM / WAT. 2

In these examples, {...} not in the term position:

 if True { ... } # always a block class foo { ... } # always a package put bar{ ... } # always a hash index 

The rest of this answer {...} means only curly code in terms of position.

A simple DWIM / WAT description for {...} in terms of

  1. The default {...} is Block . In addition, if it has a signature, several statements, or an identifier declaration, then it is Block .

  2. Otherwise, if {...} contains just a list of zero or more values ​​starting directly with the % sigil'd variable (for example, %foo ) or the Pair literal (for example :bar ), then this is Hash .

Signature means Block

Some code in brackets has an explicit signature, that is, it has explicit parameters, such as $foo below. It always creates Block no matter what is inside the braces:

 say WHAT { key => $foo, 'a', 'b' } # (Hash) say WHAT -> $foo { key => $foo, 'a', 'b' } # (Block) 

Some curly code has an implicit signature:

  • Using an explicit placeholder variable (e.g. $^foo ) inside the curly code gives it an implicit signature (with the $foo parameter in it).

  • Using a pronoun inside a curly code gives it a signature, even if it is not explicit. The pronouns $_ , @_ and %_ .

  • Even {.foo } has a signature ( (;; $_? is raw) ) due to .foo .

As in the case of an explicit signature, if the curly code has an implicit signature, it always creates Block regardless of what is inside the curly brackets:

 say WHAT { key => $_, 'a', 'b' } # (Block) say WHAT { key => 'value', .foo, .foo } # (Block) 

Several top-level operators mean that it is Block

 say WHAT { :foo; (do 'a'), (do 'b') } # (Block) say WHAT { :foo, (do 'a'), (do 'b') } # (Hash) 

The second line contains several statements, but they create values ​​in the list, which is the only top-level statement.

Declaring a top-level identifier means that it is Block

 say WHAT { :foo, (my $bar), $baz } # (Block) say WHAT { :foo, {my $bar}, $baz } # (Hash) 

The last line contains Block as the key that contains the declaration ( my $bar ). But this ad belongs to the internal Block , not the external curly code. So the inner Block is just the value for the outer code in brackets, and thus the outer block in brackets is still interpreted as Hash .

Still Block with

 my $bar = key => 'value'; say WHAT { $bar, %baz } # (Block) say WHAT { |%baz } # (Block) say WHAT { %@quux } # (Block) 

None of the above starts with the variable or literal pair % sigil'd.

When is the Hash

The code in brackets that does not fall into any of the above situations that cause it to be Block , and which is simply a list of zero or more values ​​starting either with the % sigil'd variable or with the Pair literal, creates a Hash :

 say WHAT { %foo } # (Hash) say WHAT { %foo, ... } # (Hash) say WHAT { foo => 42, ... } # (Hash) say WHAT { :foo, ... } # (Hash) say WHAT { key => $foo, 'a', 'b' } # (Hash) say WHAT { 'a', 'b', key => $foo } # (Block) 

The last block above does not start with %foo or a literal pair.

 say WHAT { %foo, 'a', 'b' } # (Hash) say WHAT { Pair.new('key',$foo), # Pair.new is NOT a literal 'a', 'b' } # (Block) 

The second block above does not start with %foo or a literal pair.

Force interpretation of Block or Hash

  • To write an empty Block , write {;} . To write an empty Hash , write {} .

  • To force figured code to create Block instead of Hash , write a ; at the beginning that is {;... } {;... }

  • To code in Hash instead of Block , follow the rules above or write %(...) instead of {...} .

Footnotes

1 See comments below for an answer to a question about the term of a position.

2 A decent DWIM should work for the benefit of most programmers most of the time, and the associated WAT should be acceptable to the community. (A WAT refers to a developer’s surprise when DWIM does not do what it meant. For each DWIM, there is one or more WATs.)

Acceptable WATs bark worse than their bites . Like all DWIMs, this may require vigilance and community feedback to ensure that it remains a net gain, not worthy of condemnation, and community members disagree on how harmful its bite is. Compare my point of view with Sam, answer this question.

+10
source share

All Articles