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 { ... }
The rest of this answer {...} means only curly code in terms of position.
A simple DWIM / WAT description for {...} in terms of
The default {...} is Block . In addition, if it has a signature, several statements, or an identifier declaration, then it is Block .
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' }
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' }
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 }
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 }
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 }
The last block above does not start with %foo or a literal pair.
say WHAT { %foo, 'a', 'b' }
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.