=begin pod

=TITLE class Pair

=SUBTITLE Key/value pair

    class Pair does Associative {}

Consists of two parts, a I<key> and a I<value>. C<Pair>s can be seen as the
atomic units in C<Hash>es, and they are also used in conjunction with named
arguments and parameters.

X<|colon pair (Pair)>
X<|:> X«| => » X<|:!> X<|:$>
There are many syntaxes for creating C<Pair>s:

    Pair.new('key', 'value'); # The canonical way
    'key' => 'value';         # this...
    :key<value>;              # ...means the same as this
    :key<value1 value2>;      # But this is  key => <value1 value2>
    :foo(127);                # short for  foo => 127
    :127foo;                  # the same   foo => 127

Variants of this are

    :key;                     # same as   key => True
    :!key;                    # same as   key => False

X<|colon list (Pair)>
Colon pairs can be chained without a comma to create a List of Pairs. Depending
on context you may have to be explicit when assigning colon lists.

    sub s(*%h){ say %h.perl };
    s :a1:b2;
    # OUTPUT: «{:a1, :b2}␤»

    my $manna = :a1:b2:c3;
    say $manna.WHAT;
    # OUTPUT: «(Pair)␤»

    $manna = (:a1:b2:c3);
    say $manna.WHAT;
    # OUTPUT: «(List)␤»

Any variable can be turned into a C<Pair> of its name and its value.

    my $bar = 10;
    my %h = :$bar;
    dd %h;  # OUTPUT: «Hash %h = {:bar(10)}␤»

=head1 Methods

=head2 method antipair

Defined as:

    method antipair(--> Pair:D)

Returns a new C<Pair> object with key and value exchanged.

    my $p = (6 => 'Perl').antipair;
    say $p.key;         # OUTPUT: «Perl␤»
    say $p.value;       # OUTPUT: «6␤»

=head2 method key

Defined as:

    multi method key(Pair:D:)

Returns the I<key> part of the C<Pair>.

    my $p = (Perl => 6);
    say $p.key; # OUTPUT: «Perl␤»

=head2 method value

Defined as:

    multi method value(Pair:D:) is rw

Returns the I<value> part of the C<Pair>.

    my $p = (Perl => 6);
    say $p.value; # OUTPUT: «6␤»

=head2 infix cmp

Defined as:

    multi sub infix:<cmp>(Pair:D, Pair:D)

The type-agnostic comparator; compares two C<Pair>s. Compares first their
I<key> parts, and then compares the I<value> parts if the keys are equal.

    my $a = (Apple => 1);
    my $b = (Apple => 2);
    say $a cmp $b;

=head2 method fmt

Defined as:

    multi method fmt(Pair:D: Str:D $format --> Str:D)

Takes a I<format string>, and returns a string the I<key> and I<value>
parts of the C<Pair> formatted. Here's an example:

    my $pair = :Earth(1);
    say $pair.fmt("%s is %.3f AU away from the sun")
    # Prints "Earth is 1.000 AU away from the sun"

For more about format strings, see L<sprintf>.

=head2 method kv

Defined as:

    multi method kv(Pair:D: --> List:D)

Returns a two-element C<List> with the I<key> and I<value> parts of
C<Pair>, in that order. This method is a special case of the same-named
method on C<Hash>, which returns all its entries as a list of keys and
values.

    my $p = (Perl => 6);
    say $p.kv[0];
    say $p.kv[1];

=head2 method pairs

Defined as:

    multi method pairs(Pair:D:)

Returns a list of one C<Pair>, namely this one.

    my $p = (Perl => 6);
    say $p.pairs.WHAT; # OUTPUT: «(List)␤»
    say $p.pairs[0];   # OUTPUT: «(Pair)␤»

=head2 method antipairs

Defined as:

    multi method antipairs(Pair:D:)

Returns a L<List|/type/List> containing the L<antipair|/type/Pair#method_antipair>
of the invocant.

    my $p = (6 => 'Perl').antipairs;
    say $p.WHAT;                                      # OUTPUT: «(List)␤»
    say $p.first;                                     # OUTPUT: «Perl => 6␤»
    say $p.first.WHAT;                                # OUTPUT: «(Pair)␤»

=head2 method invert

Defined as:

    method invert(Pair:D:)

Returns a new C<Pair> object with key and value exchanged, just like
L<antipair|/type/Pair#method_antipair>, unless the value of the invocant does
the L<Iterable|/type/Iterable> role. In the latter case an C<Iterable> structure
of C<Pair>s is returned since C<invert> expands iterable values into multiple
pairs.

    my Pair $p1 = (6 => 'Perl');
    say $p1.invert;                                   # OUTPUT: «Perl => 6␤»
    say $p1.invert.WHAT;                              # OUTPUT: «(Pair)␤»

    my Pair $p2 = ('Perl' => (5, 6));
    say $p2.invert;                                   # OUTPUT: «(5 => Perl 6 => Perl)␤»
    say $p2.invert.WHAT;                              # OUTPUT: «(List)␤»

    my Pair $p3 = ('Perl' => { cool => 'language'});
    say $p3.invert;                                   # OUTPUT: «{cool => language => Perl}␤»
    say $p3.invert.WHAT;                              # OUTPUT: «(Hash)␤»

=head2 method keys

Defined as:

    multi method keys(Pair:D: --> List:D)

Returns a L<List|/type/List> containing the L<key|/type/Pair#method_key>
of the invocant.

    say ('Perl' => 6).keys;                           # OUTPUT: «(Perl)␤»

=head2 method values

Defined as:

    multi method values(Pair:D: --> List:D)

Returns a L<List|/type/List> containing the L<value|/type/Pair#method_value>
of the invocant.

    say ('Perl' => 6).values;                         # OUTPUT: «(6)␤»

=head2 method freeze

Defined as:

    method freeze(Pair:D:)

Makes the I<value> of the C<Pair> read-only, by removing it from its L<Scalar container|/language/containers#Scalar_containers>, and returns it.

    my $str = "apple";
    my $p = Pair.new('key', $str);
    $p.value = "orange";              # this works as expected
    $p.say;                           # OUTPUT: «key => orange␤»
    $p.freeze.say;                    # OUTPUT: «orange␤»
    $p.value = "a new apple";         # Fails
    CATCH { default { put .^name, ': ', .Str } };
    # OUTPUT: «X::Assignment::RO: Cannot modify an immutable Str␤»

=head2 method Str

Defined as:

    multi method Str(Pair:D: --> Str:D)

Returns a string representation of the invocant formatted
as I<key ~ \t ~ value>.

    my $b = eggs => 3;
    say $b.Str;                                       # eggs  3

=end pod
