Your map returns a sequence of List values, each of which contains two Pair values.
Submitting this to the hash will not automatically smooth it, and each List becomes the key or hash value.
There are several ways to get it to do what you want:
Using flat
You can use the built-in flat function to smooth out the map result so that the hash gets the sequence Pair s
<H He> ==> map { (state $n)++; +$n => ~$_, ~$_ => +$n }\ ==> flat() ==> my %elements; %elements.say;
Both map and flat return lazy sequences, so this is (theoretically) memory efficient, even if the list of items is long.
- Lateral note: I also wrote
+$n instead of $n , because the build operator => Pair (for example, a list build operator) does not “deconstruct”, its arguments are if you give it a container of goods, such as the variable $ , it will be bound to it directly, and not to the value contained in it, which will lead to the fact that the next $n++ will also affect the Pair returned from the previous iteration. Providing the operator to construct a pair of expression values instead of a variable avoids this.
Using slip
slip is the highest version of flat :
<H He> ==> map { (state $n)++; slip +$n => ~$_, ~$_ => +$n }\ ==> my %elements;
Each iteration of map now returns a value of type slip , which is similar to List , except that it automatically dissolves in any parent list, it becomes part.
Refactoring
If you're not tied to your particular approach, here are two potentially clearer ways to generate the same hash:
my @keys = 1..*; my @values = <H He>; my %elements = flat (@keys Z=> @values), (@values Z=> @keys);
Or:
my %elements = 1..* Z=> <H He>; push %elements, %elements.invert;
( Z is the meta-operator "zip")
source share