Rules / Types, classes & roles / composite

Hash Reference

Mapping from strings to itemized values

What it is #

Position in the hierarchy #

Inherits from
Does
Inherited byStash

Routines #

Signatures are reproduced from the documentation, including their declared return types. A routine listed here is part of the type's published interface; whether Raku++ implements it is a separate question, answered by the examples below.

method classify-list #

multi method classify-list(&mapper, *@list, :&as --> Hash:D)
multi method classify-list(%mapper, *@list, :&as --> Hash:D)
multi method classify-list(@mapper, *@list, :&as --> Hash:D)

Returns Hash:D.

Populates a Hash by classifying the possibly-empty @list of values using the given mapper, optionally altering the values using the :&as Callable. The @list cannot be lazy. The mapper can be a Callable that takes a single argument, an Associative, or an Iterable; this Callable is guaranteed to be called only once per item.

method categorize-list #

multi method categorize-list(&mapper, *@list, :&as --> Hash:D)
multi method categorize-list(%mapper, *@list, :&as --> Hash:D)
multi method categorize-list(@mapper, *@list, :&as --> Hash:D)

Returns Hash:D.

Populates a Hash by classifying the possibly-empty @list of values using the given mapper, optionally altering the values using the :&as Callable. The @list cannot be lazy. The mapper can be a Callable that takes a single argument, an Associative, or an Iterable. With Associative and an Iterable

method push #

method push(Hash:D: +new)

Adds the new elements to the hash with the same semantics as hash assignment, but with three exceptions: Array, the new value is pushed onto the array (instead of replacing it). an Array, old and new value are both placed into an array in the place of the old value. Example: Please note that literal pairs in the argument list may be interpreted as named arguments and as such won't end up in the Hash:

method append #

method append(+@values)

Append the provided Pairs or even sized list to the Hash. If a key already exists, turn the existing value into an Array and push new value onto that Array. Please note that you can't mix even sized lists and lists of Pairs. Also, bare Pairs or colon pairs will be treated as named arguments to .append.

method default #

method default(Hash:D:)

Returns the default value of the invocant, i.e. the value which is returned when a non existing key is used to access an element in the Hash. Unless the Hash is declared as having a default value by using the is default trait the method returns the type object (Any).

method keyof #

method keyof()

Returns the type constraint for the keys of the invocant. For normal hashes the method returns the coercion type (Str(Any)) while for non-string keys hashes the type used in the declaration of the Hash is returned.

method of #

method of(Hash:D:)

Returns the type constraint for the values of the invocant. By default, i.e., if no type constraint is given during declaration, the method returns (Mu).

routine dynamic #

method dynamic(--> Bool:D)

Returns Bool:D.

Returns True if the invocant has been declared with the is dynamic trait. If you declare a variable with the * twigil is dynamic is implied. Note that in the Scalar case you have to use the VAR method in order to get correct information. Some methods are implemented as adverbs on subscripts (consult the operators documentation

Examples, run three ways #

Every example below comes from the official documentation, together with the output that documentation asserts. Each was then executed by Rakudo and by Raku++ when this page was built. Where the three agree, one result is shown; where they do not, all three are — because which of them is wrong is exactly the information worth having.

3 all-differ · 1 doc-drift · 20 no-output · 1 not-runnable · 27 ok · 1 rakudo-differs · 1 rakupp-differs

class Hash is Map { }

Not executed: the documentation states no expected output for this example.

# initialization with pairs:
my %capitals = Spain => 'Madrid', 'United States' => 'Washington DC';

Not executed: the documentation states no expected output for this example.

# adding another pair:
%capitals{'Zimbabwe'} = 'Harare';

Not executed: the documentation states no expected output for this example.

# accessing a value by key:
my $country = 'Spain';
say "The capital of $country is %capitals{$country}";

Not executed: the documentation states no expected output for this example.

# getting all keys:
say "I know the capitals of these countries: ", %capitals.keys.sort.join(', ');

Not executed: the documentation states no expected output for this example.

# check if a key is in a hash:
if %capitals{'Europe'}:exists {
    # not executed
}

Not executed: the documentation states no expected output for this example.

# iterating over keys and values (unordered):
for %capitals.kv -> $country, $capital {
    say "$capital is the capital of $country";
}

Not executed: the documentation states no expected output for this example.

my %orig = :1a, :2b; my %new = :5b, :6c;
%orig{ %new.keys } = %new.values;
say %orig.raku; # OUTPUT: «{:a(1), :b(5), :c(6)}␤»
Output
{:a(1), :b(5), :c(6)}

Documentation, Rakudo and Raku++ all agree.

given 3 { say WHAT {3 => 4, :b}  };     # OUTPUT: «(Hash)␤»
given 3 { say WHAT {3 => 4, :b($_)} };  # OUTPUT: «(Block)␤»
given 3 { say WHAT {3 => 4, :b(.Num)} };# OUTPUT: «(Block)␤»
say { 'a',:b(3), 'c' }.^name;           # OUTPUT: «Block␤»
Output
(Hash)
(Block)
(Block)
Block

Documentation, Rakudo and Raku++ all agree.

say %( 'a', 3, :b(3), 'c', 3 ).^name; # OUTPUT: «Hash␤»
Output
Hash

Documentation, Rakudo and Raku++ all agree.

say %(«a b c 1 2 3»).^name;           # OUTPUT: «Hash␤»
Output
Hash

Documentation, Rakudo and Raku++ all agree.

say %().^name; # OUTPUT: «Hash␤»
say {}.^name;  # OUTPUT: «Hash␤»
Output
Hash
Hash

Documentation, Rakudo and Raku++ all agree.

my %next-prime{Int} = 2 => 3, 3 => 5, 5 => 7, 7 => 11, 11 => 13;

Not executed: the documentation states no expected output for this example.

my Array %lists;

Not executed: the documentation states no expected output for this example.

my Array %next-primes{Int} = 2 => [3, 5], 11 => [13, 17];

Not executed: the documentation states no expected output for this example.

say % .classify-list: { $_ %% 2 ?? 'even' !! 'odd' }, ^10;
# OUTPUT: «{even => [0 2 4 6 8], odd => [1 3 5 7 9]}␤»

my @mapper = <zero one two three four five>;
my %hash = foo => 'bar';
say %hash.classify-list: @mapper, 1, 2, 3, 4, 4;
# OUTPUT: «{foo => bar, four => [4 4], one => [1], three => [3], two => [2]}␤»
Output
{even => [0 2 4 6 8], odd => [1 3 5 7 9]}
{foo => bar, four => [4 4], one => [1], three => [3], two => [2]}

Documentation, Rakudo and Raku++ all agree.

say % .classify-list: {
    [
        (.is-prime ?? 'prime' !! 'non-prime'),
        ($_ %% 2   ?? 'even'  !! 'odd'      ),
    ]
}, ^10;
# OUTPUT:
# {
#     non-prime => {
#         even => [0 4 6 8],
#         odd  => [1 9]
#     },
#     prime => {
#         even => [2],
#         odd  => [3 5 7]
#     }
# }

Not executed: the documentation states no expected output for this example.

my @mapper = [['1a','1b','1c'],['2a','2b','2c'],['3a','3b','3c']];
say % .classify-list: @mapper, 1,2,1,1,2,0;
# OUTPUT: «{1a => {1b => {1c => [0]}}, 2a => {2b => {2c => [1 1 1]}}, 3a => {3b => {3c => [2 2]}}}␤»
Output
{1a => {1b => {1c => [0]}}, 2a => {2b => {2c => [1 1 1]}}, 3a => {3b => {3c => [2 2]}}}

Documentation, Rakudo and Raku++ all agree.

my @mapper = [['1a','1b'],['2a','2b'],['3a','3b']];
say % .classify-list: @mapper, 1,0,1,1,1,0,2;
# OUTPUT: «{1a => {1b => [0 0]}, 2a => {2b => [1 1 1 1]}, 3a => {3b => [2]}}␤»
Output
{1a => {1b => [0 0]}, 2a => {2b => [1 1 1 1]}, 3a => {3b => [2]}}

Documentation, Rakudo and Raku++ all agree.

my @mapper = [<1a 1b>, <2a 2b 2fail>];
say % .classify-list: @mapper, 1,0,1,1,1,0;
# OUTPUT: «mapper on classify-list computed to an item with different number
# of elements in it than previous items, which cannot be used because all
# values need to have the same number of elements. Mixed-level classification
# is not supported.␤  in block <unit>…»

Not executed: the documentation states no expected output for this example.

say % .classify-list: :as{"Value is $_"}, { $_ %% 2 ?? 'even' !! 'odd' }, ^5;
# OUTPUT (slightly altered manually, for clarity):
# {
#     even => ['Value is 0', 'Value is 2', 'Value is 4'],
#     odd  => ['Value is 1', 'Value is 3']
# }

Not executed: the documentation states no expected output for this example.

say % .categorize-list: {
    gather {
        take 'prime'   if .is-prime;
        take 'largish' if $_ > 5;
        take $_ %% 2 ?? 'even' !! 'odd';
    }
}, ^10;

Not executed: the documentation states no expected output for this example.

# OUTPUT:
# {
#     prime   => [2 3 5 7]
#     even    => [0 2 4 6 8],
#     odd     => [1 3 5 7 9],
#     largish => [6 7 8 9],
# }

Not executed: the documentation states no expected output for this example.

say % .categorize-list: {
    [
        $_ > 5    ?? 'largish' !! 'smallish',
        .is-prime ?? 'prime'   !! 'non-prime',
    ],
}, ^10;

Not executed: the documentation states no expected output for this example.

# OUTPUT:
# {
#     largish => {
#         non-prime => [6 8 9],
#         prime     => [7]
#     },
#     smallish => {
#         non-prime => [0 1 4],
#         prime     => [2 3 5]
#     }
# }

Not executed: the documentation states no expected output for this example.

say % .categorize-list: :as{"Value is $_"}, { $_ %% 2 ?? 'even' !! 'odd' }, ^5;
# OUTPUT (slightly altered manually, for clarity):
# {
#     even => ['Value is 0', 'Value is 2', 'Value is 4'],
#     odd  => ['Value is 1', 'Value is 3']
# }

Not executed: the documentation states no expected output for this example.

my %h  = a => 1;
%h.push: (a => 1);              # a => [1,1]
%h.push: (a => 1) xx 3 ;        # a => [1,1,1,1,1]
%h.push: (b => 3);              # a => [1,1,1,1,1], b => 3
%h.push('c' => 4);              # a => [1,1,1,1,1], b => 3, c => 4
push %h, 'd' => 5;              # a => [1,1,1,1,1], b => 3, c => 4, d => 5

Not executed: the documentation states no expected output for this example.

my %h .= push(e => 6);
say %h.raku; # OUTPUT: «{}␤»
Output
{}

Documentation, Rakudo and Raku++ all agree.

push my %h, f => 7;
CATCH { default { put .message } };
# OUTPUT: «Unexpected named argument 'f' passed␤»
Documentation
Unexpected named argument 'f' passed
Rakudo
Cannot resolve caller push(Hash:D, :f(Int)); none of these signatures matches:
    (\a, \b)
    (\a, **@b is raw)
Raku++

All three differ. Needs a human.

Not yet examined. Which of these is correct has not been established — do not treat either engine as settled here.

my %wc = 'hash' => 323, 'pair' => 322, 'pipe' => 323;
(my %inv).push: %wc.invert;
say %inv;                     # OUTPUT: «{322 => pair, 323 => [pipe hash]}␤»
Documentation
{322 => pair, 323 => [pipe hash]}
Rakudo
{322 => pair, 323 => [pipe hash]}
Raku++
{322 => pair, 323 => [hash pipe]}

Raku++ disagrees with both the documentation and Rakudo — a defect.

my %wc = 'hash' => 323, 'pair' => 322, 'pipe' => 323;
my %inv .= push: %wc.invert;

Not executed: the documentation states no expected output for this example.

my %ha = :a[42, ]; %ha.push: "a" => <a b c a>;
say %ha; # OUTPUT: «{a => [42 (a b c a)]}␤»
Output
{a => [42 (a b c a)]}

Documentation, Rakudo and Raku++ all agree.

my %hb = :a[42, ]; %hb.append: "a" => <a b c a>;
say %hb; # OUTPUT: «{a => [42 a b c a]}␤»
Output
{a => [42 a b c a]}

Documentation, Rakudo and Raku++ all agree.

my %h = a => 1;
%h.append('b', 2, 'c', 3);
%h.append( %(d => 4) );
say %h;
# OUTPUT: «{a => 1, b => 2, c => 3, d => 4}␤»
%h.append('a', 2);
# OUTPUT: «{a => [1 2], b => 2, c => 3, d => 4}␤»
Documentation
{a => 1, b => 2, c => 3, d => 4}
{a => [1 2], b => 2, c => 3, d => 4}
Rakudo
{a => 1, b => 2, c => 3, d => 4}
Raku++
{a => 1, d => 4}

All three differ. Needs a human.

Not yet examined. Which of these is correct has not been established — do not treat either engine as settled here.

my %hb = :a[42, ]; %hb.append: "a" => <a b c a>;
say %hb; # OUTPUT: «{a => [42 a b c a]}␤»
Output
{a => [42 a b c a]}

Documentation, Rakudo and Raku++ all agree.

my %ha = :a[42, ]; %ha.push: "a" => <a b c a>;
say %ha; # OUTPUT: «{a => [42 (a b c a)]}␤»
Output
{a => [42 (a b c a)]}

Documentation, Rakudo and Raku++ all agree.

my %h1 = 'apples' => 3, 'oranges' => 7;
say %h1.default;                                       # OUTPUT: «(Any)␤»
say %h1{'bananas'};                                    # OUTPUT: «(Any)␤»
Output
(Any)
(Any)

Documentation, Rakudo and Raku++ all agree.

my %h2 is default(1) = 'apples' => 3, 'oranges' => 7;
say %h2.default;                                       # OUTPUT: «1␤»
say %h2{'apples'} + %h2{'bananas'};                    # OUTPUT: «4␤»
Output
1
4

Documentation, Rakudo and Raku++ all agree.

my %h1 = 'apples' => 3, 'oranges' => 7;  # (no key type specified)
say %h1.keyof;                           # OUTPUT: «(Str(Any))␤»
Output
(Str(Any))

Documentation, Rakudo and Raku++ all agree.

my %h2{Str} = 'oranges' => 7;            # (keys must be of type Str)
say %h2.keyof;                           # OUTPUT: «(Str)␤»
%h2{3} = 'apples';                       # throws exception
CATCH { default { put .^name, ': ', .Str } };
# OUTPUT: «X::TypeCheck::Binding: Type check failed in binding to key; expected Str but got Int (3)␤»
Documentation
(Str)
X::TypeCheck::Binding: Type check failed in binding to key; expected Str but got Int (3)
Rakudo
(Str)
X::TypeCheck::Binding::Parameter: Type check failed in binding to parameter 'key'; expected Str but got Int (3)
Raku++
(Str)

All three differ. Needs a human.

Not yet examined. Which of these is correct has not been established — do not treat either engine as settled here.

my %h3{Int};                             # (this time, keys must be of type Int)
%h3{42} = 4096;
say %h3.keyof;                           # OUTPUT: «(Int)␤»
Output
(Int)

Documentation, Rakudo and Raku++ all agree.

my %h1 = 'apples' => 3, 'oranges' => 7;  # (no type constraint specified)
say %h1.of;                              # OUTPUT: «(Mu)␤»
Output
(Mu)

Documentation, Rakudo and Raku++ all agree.

my Int %h2 = 'oranges' => 7;             # (values must be of type Int)
say %h2.of;                              # OUTPUT: «(Int)␤»
Output
(Int)

Documentation, Rakudo and Raku++ all agree.

my %a;
say %a.dynamic;                          # OUTPUT: «False␤»
Output
False

Documentation, Rakudo and Raku++ all agree.

my %b is dynamic;
say %b.dynamic;                          # OUTPUT: «True␤»
Output
True

Documentation, Rakudo and Raku++ all agree.

my %*b;
say %*b.dynamic;                         # OUTPUT: «True␤»
Output
True

Documentation, Rakudo and Raku++ all agree.

my $s is dynamic = %('apples' => 5);
say $s.dynamic;                   # OUTPUT: «False␤»  (wrong, don't do this)
say $s.VAR.dynamic;               # OUTPUT: «True␤»   (correct approach)
Output
False
True

Documentation, Rakudo and Raku++ all agree.

my %h = a => 1, b => 2;
say %h<a>:exists;   # OUTPUT: «True␤»
say %h<a b>:exists; # OUTPUT: «(True True)␤»
Output
True
(True True)

Documentation, Rakudo and Raku++ all agree.

my %h = a => 1;
say %h;         # OUTPUT: «{a => 1}␤»
say %h.elems;   # OUTPUT: «1␤»
Output
{a => 1}
1

Documentation, Rakudo and Raku++ all agree.

%h<a>:delete;
say %h;         # OUTPUT: «{}␤»
say %h.elems;   # OUTPUT: «0␤»

Neither engine can run this in isolation — the example depends on context from the surrounding text.

my %h = a => 1, b => 2;
say %h<a>:p;    # OUTPUT: «a => 1␤»
say %h<a b>:p;  # OUTPUT: «(a => 1 b=> 2)␤»
Documentation
a => 1
(a => 1 b=> 2)
Rakudo
a => 1
(a => 1 b => 2)
Raku++
a => 1
(a => 1 b => 2)

Both engines agree; the documentation states something else. Trust the engines.

my %h = a => 1, b => 2;
say %h<a>:k;    # OUTPUT: «a␤»
say %h<a b>:k;  # OUTPUT: «(a b)␤»
Output
a
(a b)

Documentation, Rakudo and Raku++ all agree.

my %h = a => 1, b => 2, c => 3;
say %h<a c>:kv;  # OUTPUT: «(a 1 c 3)␤»
Output
(a 1 c 3)

Documentation, Rakudo and Raku++ all agree.

my %h1 = a => 1;
my %h2 = a => 1, b => 2;
say %h1<>:k; # OUTPUT: «(a)␤»
say %h1<>:v; # OUTPUT: «(1)␤»
say %h2<>:k; # OUTPUT: «(a b)␤»
say %h2<>:v; # OUTPUT: «(1 2)␤»
Documentation
(a)
(1)
(a b)
(1 2)
Rakudo
(a)
(1)
(b a)
(2 1)
Raku++
(a)
(1)
(a b)
(1 2)

Raku++ matches the documentation; Rakudo does not. This is the one class where neither engine can be assumed right: it may be a stale doc that Raku++ was built from, or it may be a Rakudo bug that the documentation predates. Each case is examined individually.

Not yet examined. Which of these is correct has not been established — do not treat either engine as settled here.