Your question1 and this answer only apply to braced code ({...}
) in term position2.
The Rule
If braced code does not have a signature or include top level statements, and is empty or contains just a list whose first element is a %
sigil'd variable (eg %foo
) or a literal pair (eg :bar
), it's a Hash
:
say WHAT { } # (Hash)
say WHAT { %foo } # (Hash)
say WHAT { %foo, ... } # (Hash)
say WHAT { foo => 42, ... } # (Hash)
say WHAT { :foo, ... } # (Hash)
say WHAT { key => $foo, ... } # (Hash)
Otherwise it's a Block
.
To force Hash
, or Block
, interpretation
To write an empty Hash
term, write {}
.
To write an empty Block
term, write {;}
.
To force a {...}
term to construct a Block
instead of a Hash
, include a ;
, eg {; ... }
.
To force a {...}
term to construct a Hash
instead of a Block
, follow the rule per summary above / details below (or write %(...)
instead of braced code).
Detailed examples
The rest of this answer provides exhaustive details in case anyone thinks the relatively simple rule above is wrong.
Some braced code has an explicit signature, i.e. it has explicit parameters such as $foo
below. It always constructs a Block
no matter what's inside the braces:
say WHAT { key => $foo, 'a', 'b' } # (Hash)
say WHAT -> $foo { key => $foo, 'a', 'b' } # (Block)
Some braced code has an implicit signature that is generated due to syntax encountered within the braces:
Use of a "pronoun" ($_
, @_
or %_
) inside braced code. This results in a Block
with a signature (an implicit one if there's no explicit one). Use of @_
or %_
pronouns is always explicit; use of $_
can be explicit, or implied if there's a methodop such as .method
with no left hand side argument. In other words, even { :foo, .key, .value }
is a Block
with a signature ((;; $_? is raw)
) due to .key
's lack of a left hand side argument.
Use of a "placeholder" variable (e.g. $^foo
).
As with an explicit signature, if braced code has an implicit signature then it always constructs a Block
no matter what's inside the braces:
say WHAT { key => @_ } # (Block)
say WHAT { key => 'value', .foo, .bar } # (Block)
Top level statements mean it's a Block
:
say WHAT { :foo; (do 'a'), (do 'b') } # (Block)
say WHAT { :foo, (do 'a'), (do 'b') } # (Hash)
The braced code in the first line starts with :foo;
; the ;
means the braced code contains statements.
The second line contains multiple statements but the braced code doesn't see them as top level statements. Instead they're producing values within individual elements of a list -- which is not itself a statement.
A top level declaration of an identifier also mean it's a Block
. A declaration is a statement, but I've included this bit just in case someone doesn't realize that:
say WHAT { :foo, $baz, {my $bar} } # (Hash)
say WHAT { :foo, $baz, (my $bar) } # (Block)
The first line contains a Block
as a value that contains a declaration (my $bar
). But that declaration belongs to the inner {my $bar}
Block
, not the outer {...}
. So the inner Block
is just a value as far as the outer {...}
is concerned, and thus that outer braced code is still interpreted as a Hash
.
In contrast the second line declares a variable inside parentheses within the {...}
. So the braced code is a Block
.
As noted at the start, to be a Hash
, the content of braced code must be a list that begins with either a %
sigil'd variable or a literal pair. So these all produce Block
s instead:
my $bar = key => 'value';
say WHAT { $bar, %baz } # (Block)
say WHAT { |%baz } # (Block)
say WHAT { %@quux } # (Block)
say WHAT { 'a', 'b', key => $foo } # (Block)
say WHAT { Pair.new: 'key', $foo } # (Block)
Footnotes
1 This "Hash
or Block
?" question is an example of DWIM design. In Raku culture, good DWIM design is considered a good thing. But every DWIM comes with corresponding WATs3. The key to good DWIM design is ensuring that, in general, WATs' barks are worse than their bites4; and that the barks are useful5; and that the net benefits of the DWIM are considered to far outweigh all the barking and biting.6
2 A term is Raku's analog of a noun or noun phrase in English. It's a value.
Examples of braced code that are terms:
.say given { ... } # closure? hash?
say 42, { ... } # closure? hash?
Examples of braced code that are not terms:
if True { ... } # always a closure
class foo { ... } # always a package
put bar{ ... } # always a hash index
This answer only discusses braced code that are terms. For more details about terms, or more specifically "term position" (places in the grammar where a braced code will be interpreted as a term), see the comments below this answer.
3 WAT refers to a dev's incredulous surprise when something seems crazy to them. It's known that, even for well designed DWIMs, for each one that works for most folk, most of the time, there are inevitably one or more related WATs that surprise some folk, some of the time, including some of the same folk who at other times benefit from the DWIM.
4 The bite of the WATs related to this DWIM varies. It's typically a bark (error message) that makes the problem obvious. But it can also be much more obscure:
say { a => 42 }() ; # No such method 'CALL-ME' for invocant of type 'Hash' WAT? Oh.
say { a => $_ }<a> ; # Type Block does not support associative indexing. WAT? Oh.
say { a => $_, b => 42, c => 99 } .elems # 1 WAT?????
5 A "bark" is an error message or warning in documentation. These can often be improved. cf Lock.protect({}) fails, but with surprising message.
6 Community member opinions differ on whether DWIM design in general, or any given DWIM in particular, is worth it. cf my perspective vs Sam's answer to this question.