Skip to content

Commit 286e135

Browse files
committed
Be more clear about %() being preferred to { } for hash creation
Work on fixing #1380 In addition to more highly recommending %(), we also use less text and make the examples of the pitfalls more clear.
1 parent b90d2f8 commit 286e135

File tree

1 file changed

+23
-54
lines changed

1 file changed

+23
-54
lines changed

doc/Type/Hash.pod6

Lines changed: 23 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,19 @@ occurrence is stored in the hash:
6060
my %h = a => 1, a => 2;
6161
say %h<a>; # OUTPUT: «2␤»
6262
63-
To assign to a variable without the C<%> sigil, you may use curly braces:
63+
To assign to a variable without the C<%> sigil, you may use the C<%()> hash
64+
constructor:
6465
65-
my $h = { a => 1, b => 2 }; # *See Note*
66+
my $h = %( a => 1, b => 2 );
6667
say $h.WHAT; # OUTPUT: «(Hash)␤»
6768
say $h<a>; # OUTPUT: «1␤»
6869
69-
B<NOTE:> If one or more values reference the topic variable, C<$_>, the
70+
B<NOTE:> Hashes can also be constructed with C<{ }> similarly to how they are
71+
in Perl 5. It is recommended to use the C<%()> hash constructor, as braces
72+
are reserved for creating L<Block|/type/Block> objects and therefore braces
73+
only create Hash objects in specific circumstances.
74+
75+
If one or more values reference the topic variable, C<$_>, the
7076
right-hand side of the assignment will be interpreted as a L<Block|/type/Block>,
7177
not a Hash:
7278
@@ -79,63 +85,22 @@ not a Hash:
7985
sub lookup-user (Hash $h) { #`(Do something...) $h }
8086
8187
my @names = map {
88+
# While this creates a hash:
89+
my $query = { name => "$person<firstName> $person<lastName>" };
90+
say $query.WHAT; # OUTPUT: «(Hash)␤»
91+
# And this also makes a hash
92+
# Doing this will create a Block. Oh no!
8293
my $query = { name => "$_<firstName> $_<lastName>" };
83-
say $query.WHAT; # OUTPUT: «(Block)␤»
84-
say $query<name>; # fails
94+
say $query2.WHAT; # OUTPUT: «(Block)␤»
95+
say $query2<name>; # fails
96+
8597
CATCH { default { put .^name, ': ', .Str } };
8698
# OUTPUT: «X::AdHoc: Type Block does not support associative indexing.␤»
8799
lookup-user($query); # Type check failed in binding $h; expected Hash but got Block
88100
}, @people;
89101
90-
Instead, you should either:
91-
92-
=begin item
93-
1) use the C<%()> hash constructor:
94-
95-
=for code :skip-test
96-
my $query = %( name => "$_<firstName> $_<lastName>" );
97-
say $query.WHAT; # OUTPUT: «(Hash)␤»
98-
say $query<name>; # Andy Adams, Beth Burke, etc.
99-
=end item
100-
101-
=begin item
102-
2) assign to a Hash type (C<%>) directly:
103-
104-
=for code :skip-test
105-
my %query = name => "$_<firstName> $_<lastName>"; # No braces required
106-
say %query.WHAT; # OUTPUT: «(Hash)␤»
107-
say %query<name>; # Andy Adams, Beth Burke, etc.
108-
=end item
109-
110-
=begin item
111-
or 3) simply avoid the issue altogether by explicitly providing a name for
112-
the topic variable:
113-
114-
my @people = [
115-
{ id => "1A", firstName => "Andy", lastName => "Adams" },
116-
{ id => "2B", firstName => "Beth", lastName => "Burke" }
117-
];
118-
sub lookup-user (Hash $h) { #`(Do something...) $h }
119-
my @names = map -> $person {
120-
my $query = { name => "$person<firstName> $person<lastName>" };
121-
say $query.WHAT; # OUTPUT: «(Hash)␤»
122-
say $query<name>; # Andy Adams, Beth Burke, etc.
123-
124-
lookup-user($query);
125-
}, @people;
126-
=end item
127-
128-
Even in the final case, however, specifying a Hash type (C<%>) is still the
129-
most idiomatic and unambiguous solution:
130-
131-
my @people = [
132-
{ id => "1A", firstName => "Andy", lastName => "Adams" },
133-
{ id => "2B", firstName => "Beth", lastName => "Burke" }
134-
];
135-
sub lookup-user (Hash $h) { #`(Do something...) $h }
136-
my @names = @people.map: -> $person {
137-
lookup-user( %( name => "$person<firstName> $person<lastName>" ) );
138-
};
102+
Instead, you should use the C<%()> hash constructor and only use C<{}> for
103+
creating Block's.
139104
140105
=head2 Slices
141106
@@ -156,6 +121,10 @@ Note that with objects as keys, you cannot access non-string keys as strings:
156121
:{ -1 => 41, 0 => 42, 1 => 43 }<0>; # Any
157122
:{ -1 => 41, 0 => 42, 1 => 43 }{0}; # 42
158123
124+
Note: The same pitfalls explained about C<{}> sometimes creating Block's also
125+
apply to C<:{}>. At this time there is no C<%()> version for creating non-string
126+
keys.
127+
159128
=head2 Constraint value types
160129
161130
Place a type object in-between the declarator and the name to constraint the type

0 commit comments

Comments
 (0)