Today, we will take a look at a few methods of the Hash class that return all hash keys or values or both:
> my %h = H => 'Hydrogen', He => 'Helium', Li => 'Lithium';
{H => Hydrogen, He => Helium, Li => Lithium}
> %h.keys;
(H Li He)
> %h.values;
(Hydrogen Lithium Helium)
> %h.kv;
(H Hydrogen Li Lithium He Helium)
While you may want to go directly to the src/core/Hash.pm6 file to see the definitions of the methods, you will not find them there. The Hash class is a child of Map, and all these methods are defined in src/core/Map.pm6. Getting keys and values is simple:
multi method keys(Map:D:) {
Seq.new(Rakudo::Iterator.Mappy-keys(self))
}
multi method values(Map:D:) {
Seq.new(Rakudo::Iterator.Mappy-values(self))
}
For the kv method, more work has to be done:
multi method kv(Map:D:) {
Seq.new(class :: does Rakudo::Iterator::Mappy {
has int $!on-value;
method pull-one() is raw {
. . .
}
method skip-one() {
. . .
}
method push-all($target --> IterationEnd) {
. . .
}
}.new(self))
}
As you see, the method returns a sequence that is built using an anonymous class implementing the Rakudo::Iterator::Mappy role. We already saw how this approach is used in combination with defining pull-one and push-all methods.
Let us look at another set of methods, pairs and antipairs. One of them is simple and straightforward:
multi method pairs(Map:D:) {
Seq.new(self.iterator)
}
Another one is using an intermediate class:
multi method antipairs(Map:D:) {
Seq.new(class :: does Rakudo::Iterator::Mappy {
method pull-one() {
. . .
}
method push-all($target --> IterationEnd) {
. . .
}
}.new(self))
}
Both methods produce results of the same structure:
> %h.antipairs (Hydrogen => H Lithium => Li Helium => He) > %h.pairs (H => Hydrogen Li => Lithium He => Helium)
One thought on “🔬73. Keys, values, etc. of hashes in Perl 6”