=begin pod :kind("Type") :subkind("role") :category("composite")

=TITLE role Associative

=SUBTITLE Object that supports looking up values by key

    role Associative[::TValue = Mu, ::TKey = Str(Any)] { }

A common role for types that support name-based lookup through
L«postcircumfix:<{ }>|/language/operators#postcircumfix_{_}» such as
L<Hash|/type/Hash> and L<Map|/type/Map>. It is used for type checks in operators
that expect to find specific methods to call. See
L<Subscripts|/language/subscripts#Methods_to_implement_for_associative_subscripting>
for details.

The C<%> sigil restricts variables to objects that do C<Associative>, so you
will have to mix in that role if you want to use it for your classes.

=begin code
class Whatever {};
my %whatever := Whatever.new;
# OUTPUT: «Type check failed in binding; expected Associative but got Whatever
=end code

Please note that we are using binding C<:=> here, since by default C<%>
assignments expect a C<Hash> in the right-hand side, and thus assignment
would try and convert it to a hash (also failing). However, with the
Associative role:

    class Whatever is Associative {};
    my %whatever := Whatever.new;

will be syntactically correct.

=head1 Methods

=head2 method of

Defined as:

    method of()

C<Associative>, as the definition above shows, is actually a
L<parameterized role|/language/objects#Parameterized_roles>
which can use different classes for keys and values. As seen at the top of the
document, by default it coerces the key to C<Str> and uses a very
generic C<Mu> for value.

    my %any-hash;
    say %any-hash.of; # OUTPUT: «(Mu)␤»

The value is the first parameter you use when instantiating C<Associative> with
particular classes:

    class DateHash is Hash does Associative[Cool,DateTime] {};
    my %date-hash := DateHash.new;
    say %date-hash.of; # OUTPUT: «(Cool)␤»

=head2 method keyof

Defined as:

    method keyof()

Returns the parameterized key used for the Associative role, which is C<Any>
coerced to C<Str> by default. This is the class used as second parameter when
you use the parameterized version of Associative.

    my %any-hash;
    %any-hash.keyof; # OUTPUT: «(Str(Any))␤»

=head1 Methods that classes mixing Associative should provide

You need to provide these methods if you want your class to implement the
Associative role properly and, thus, use the C<{}> operator for accessing the
value given a key. They are not mandatory, however; on the other hand, if you
simply want objects of a class to use C<{}>, you can implement them without
mixing the C<Associative> role.

=head2 method AT-KEY

    method AT-KEY(\key)

Should return the value / container at the given key.

=for code
class What { method AT-KEY(\key) { 42 }};
say What.new{33}; # OUTPUT: «42␤»

=head2 method EXISTS-KEY

    method EXISTS-KEY(\key)

Should return a C<Bool> indicating whether the given key actually has a value.

=head2 method STORE

    method STORE(\values, :$INITIALIZE)

This method should only be supplied if you want to support the:

=for code :preamble<role Foo {}>
my %h is Foo = a => 42, b => 666;

syntax for binding your implementation of the C<Associative> role.

Should accept the values to (re-)initialize the object with, which either
could consist of C<Pair>s, or separate key/value pairs.  The optional
named parameter will contain a C<True> value when the method is called on
the object for the first time.  Should return the invocant.

=head1 See also

See
L<Methods to implement for associative subscripting|/language/subscripts#Methods_to_implement_for_associative_subscripting>
for information about additional methods that can be implemented for the
C<Associative> role.

=end pod

# vim: expandtab softtabstop=4 shiftwidth=4 ft=perl6
