class Pair
class Pair does Associative {}
Consists of two parts, a key and a value. Pair
s can be seen as the
atomic units in Hashes, and they are also used in conjunction with named
arguments and parameters.
|Syntax,=>
There are many syntaxes for creating 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
Note that last form supports Non-ASCII numerics as well:
# use MATHEMATICAL DOUBLE-STRUCK DIGIT THREE
say (:šmath-three); # OUTPUT: Ā«math-three => 3ā¤Ā»
But not synthetic (i.e. formed by a digit and additional Unicode marks):
say :7Ģa
You can also use an identifier-like literal as key; this will not need the quotes as long as it follows the syntax of ordinary identifiers:
(foo => 127) # the same foo => 127
Variants of this are
:key; # same as key => True
:!key; # same as key => False
And this other variant, to be used in routine invocation
sub colon-pair( :$key-value ) {
say $key-value;
}
my $key-value = 'value';
colon-pair( :$key-value ); # OUTPUT: Ā«valueā¤Ā»
colon-pair( key-value => $key-value ); # OUTPUT: Ā«valueā¤Ā»
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.raku };
s :a1:b2;
# OUTPUT: Ā«{:a1, :b2}ā¤Ā»
my $manna = :a1:b2:c3;
say $manna.^name;
# OUTPUT: Ā«Pairā¤Ā»
$manna = (:a1:b2:c3);
say $manna.^name;
# OUTPUT: Ā«Listā¤Ā»
Any variable can be turned into a Pair
of its name and its value.
my $bar = 10;
my $p = :$bar;
say $p; # OUTPUT: Ā«bar => 10ā¤Ā»
It is worth noting that when assigning a Scalar as value of a
Pair
the value holds the container of the value itself. This means that it is
possible to change the value from outside of the Pair
itself:
my $v = 'value A';
my $pair = a => $v;
$pair.say; # OUTPUT: Ā«a => value Aā¤Ā»
$v = 'value B';
$pair.say; # OUTPUT: Ā«a => value Bā¤Ā»
Please also note that this behavior is totally unrelated to the way used to
build the Pair
itself (i.e., explicit usage of new
, use of colon, fat
arrow), as well as if the Pair
is bound to a variable.
It is possible to change the above behavior forcing the Pair
to remove the
scalar container and to hold the effective value itself via the method
freeze:
my $v = 'value B';
my $pair = a => $v;
$pair.freeze;
$v = 'value C';
$pair.say; # OUTPUT: Ā«a => value Bā¤Ā»
As Pair implements Associative role, its value can be
accessed using Associative subscription operator, however, due to Pair's
singular nature, the pair's value will be only returned for the pair's key.
Nil object will be returned for any other key. Subscript
adverbs such as :exists
can be used on Pair.
my $pair = a => 5;
say $pair<a>; # OUTPUT: Ā«5ā¤Ā»
say $pair<a>:exists; # OUTPUT: Ā«Trueā¤Ā»
say $pair<no-such-key>; # OUTPUT: Ā«Nilā¤Ā»
Methods
method new
multi method new(Pair: Mu $key, Mu $value)
multi method new(Pair: Mu :$key, Mu :$value)
Constructs a new Pair
object.
method ACCEPTS
multi method ACCEPTS(Pair:D $: %topic)
multi method ACCEPTS(Pair:D $: Pair:D $topic)
multi method ACCEPTS(Pair:D $: Mu $topic)
If %topic
is an Associative, looks up the value using invocant's key in
it and checks invocant's value .ACCEPTS
that value:
say %(:42a) ~~ :42a; # OUTPUT: Ā«Trueā¤Ā»
say %(:42a) ~~ :10a; # OUTPUT: Ā«Falseā¤Ā»
If $topic
is another Pair
, checks the invocant's key and value
.ACCEPTS
the $topic
's key and value respectively:
say :42a ~~ :42a; # OUTPUT: Ā«Trueā¤Ā»
say :42z ~~ :42a; # OUTPUT: Ā«Falseā¤Ā»
say :10a ~~ :42a; # OUTPUT: Ā«Falseā¤Ā»
If $topic
is any other value, the invocant Pair
's key is treated as a method name.
This method is called on $topic
, the Bool result of which is compared
against the invocant Pair
's Bool value. For example, primality can
be tested using smartmatch:
say 3 ~~ :is-prime; # OUTPUT: Ā«Trueā¤Ā»
say 3 ~~ is-prime => 'truthy'; # OUTPUT: Ā«Trueā¤Ā»
say 4 ~~ :is-prime; # OUTPUT: Ā«Falseā¤Ā»
This form can also be used to check Bool values of multiple methods on the same object, such as IO::Path, by using Junctions:
say "foo" .IO ~~ :f & :rw; # OUTPUT: Ā«Falseā¤Ā»
say "/tmp".IO ~~ :!f; # OUTPUT: Ā«Trueā¤Ā»
say "." .IO ~~ :f | :d; # OUTPUT: Ā«Trueā¤Ā»
method antipair
method antipair(Pair:D: --> Pair:D)
Returns a new Pair
object with key and value exchanged.
my $p = (d => 'Raku').antipair;
say $p.key; # OUTPUT: Ā«Rakuā¤Ā»
say $p.value; # OUTPUT: Ā«dā¤Ā»
method key
multi method key(Pair:D:)
Returns the key part of the Pair
.
my $p = (Raku => "d");
say $p.key; # OUTPUT: Ā«Rakuā¤Ā»
method value
multi method value(Pair:D:) is rw
Returns the value part of the Pair
.
my $p = (Raku => "d");
say $p.value; # OUTPUT: Ā«dā¤Ā»
infix cmp
multi infix:<cmp>(Pair:D, Pair:D)
The type-agnostic comparator; compares two Pair
s. Compares first their
key parts, and then compares the value parts if the keys are equal.
my $a = (Apple => 1);
my $b = (Apple => 2);
say $a cmp $b; # OUTPUT: Ā«Lessā¤Ā»
method fmt
multi method fmt(Pair:D: Str:D $format --> Str:D)
Takes a format string, and returns a string the key and value
parts of the Pair
formatted. Here's an example:
my $pair = :Earth(1);
say $pair.fmt("%s is %.3f AU away from the sun")
# OUTPUT: Ā«Earth is 1.000 AU away from the sunā¤Ā»
For more about format strings, see sprintf.
method kv
multi method kv(Pair:D: --> List:D)
Returns a two-element List with the key and value parts of
Pair
, in that order. This method is a special case of the same-named
method on Hash, which returns all its entries as a list of keys and
values.
my $p = (Raku => "d");
say $p.kv[0]; # OUTPUT: Ā«Rakuā¤Ā»
say $p.kv[1]; # OUTPUT: Ā«dā¤Ā»
method pairs
multi method pairs(Pair:D:)
Returns a list of one Pair
, namely this one.
my $p = (Raku => "d");
say $p.pairs.^name; # OUTPUT: Ā«Listā¤Ā»
say $p.pairs[0]; # OUTPUT: Ā«Raku => dā¤Ā»
method antipairs
multi method antipairs(Pair:D:)
Returns a List containing the antipair of the invocant.
my $p = (d => 'Raku').antipairs;
say $p.^name; # OUTPUT: Ā«Listā¤Ā»
say $p.first; # OUTPUT: Ā«Raku => dā¤Ā»
say $p.first.^name; # OUTPUT: Ā«Pairā¤Ā»
method invert
method invert(Pair:D: --> Seq:D)
Returns a Seq. If the .value
of the invocant is NOT an
Iterable, the Seq will contain a single Pair
whose
.key
is the .value
of the invocant and whose .value
is the .key
of
the invocant:
:foo<bar>.invert.raku.say; # OUTPUT: Ā«(:bar("foo"),).Seqā¤Ā»
If invocant's .value
is an Iterable, the returned Seq
will contain the same number of Pair
s as items in the .value
, with each
of those items a .key
of a pair and the .key
of the invocant the .value
of that pair:
:foo<Raku is great>.invert.raku.say;
# OUTPUT: Ā«(:Raku("foo"), :is("foo"), :great("foo")).Seqā¤Ā»
:foo{ :42a, :72b }.invert.raku.say;
# OUTPUT: Ā«((:a(42)) => "foo", (:b(72)) => "foo").Seqā¤Ā»
To perform the exact .key
and .value
swap, use
.antipair method.
method keys
multi method keys(Pair:D: --> List:D)
Returns a List containing the key of the invocant.
say (Raku => "d").keys; # OUTPUT: Ā«(Raku)ā¤Ā»
method values
multi method values(Pair:D: --> List:D)
Returns a List containing the value of the invocant.
say (Raku => "d").values; # OUTPUT: Ā«(d)ā¤Ā»
method freeze
method freeze(Pair:D:)
Makes the value of the Pair
read-only, by removing it from its Scalar container, 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 (apple)ā¤Ā»
NOTE: this method is deprecated as of 6.d language version. Instead,
create a new Pair
, with a decontainerized key/value.
$p.=Map.=head.say; # OUTPUT: Ā«orangeā¤Ā»
method Str
multi method Str(Pair:D: --> Str:D)
Returns a string representation of the invocant formatted as key ~ \t ~ value.
my $b = eggs => 3;
say $b.Str; # OUTPUT: Ā«eggs 3ā¤Ā»
method Pair
method Pair()
Returns the invocant Pair
object.
my $pair = eggs => 3;
say $pair.Pair === $pair; # OUTPUT: Ā«Trueā¤Ā»