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”