Perl 6 has some very sophisticated operators, and many of them naturally do the sorts of things that we do quite a bit unnaturally otherwise. The strength of these operators are the ugliness they hide from us.
Consider how I might turn a Perl 5 array into a hash, perhaps so I can use exists
to lookup an item:
#!perl5 my @array = qw( a b c d ); my %hash = map { $_ => 1 } @array;
It might seem a bit shorter to try a hash slice assignment, but I like to declare my variables. This is this a bit goofy looking:
#!perl5 my %hash; @hash{ @array } = (1) x @array;
It’s a bit harder if I want the hash value to be the array position:
#!perl5 my @array = qw( a b c d ); my %hash = map { $array[$_] => $_ } 0 .. $#array; # ... or @hash{ @array } = 0 .. $#array;
I can still do these things the hard way in Perl 6. The feed operators (==>
, also known as sequencer) makes short work of declaring a variable on one side of the expression, doing work in the middle, and having the result end up in a declared variable on the other end. It’s like an xargs
for programming languages where the result of the generating side because the final arguments of the receiving side:
#!perl6 my @array = < a b c d > ==> map( { $_ => 1 } ) ==> my %hash1;
I know I’m going to abuse those feed operators.
What if I want the array index to be the value. Or, is it? Perl 6 does quite a bit to make it easy to create lists. If you make it easy to create complex data structures, you’re going to be a nice language.
I can use the zip metaoperator, Z
to apply the item assignment operator, =>
to corresponding pairs:
my %hash2 = @array Z=> 0 .. @array.end;
This takes the first item in @array
and pairs it with the first item in the 0 .. @array.end
.
But, I don’t even need to know about the end of the array. The zip operator stops when it gets to the end of the shorter list. I don’t need to type out the name of the array again:
my %hash2 = @array Z=> 0 .. *;
The righthand side of Z=> doesn’t need to be bounded, it can be an infinite range, delimited by the lefthand side of Z=> . Again a nice use of Whatever 🙂
The very last line of code can be simplified as:
Or even:
my %hash2 = @array.map: * => $++;
Awesome! Thanks for this post! I’ll have to remember “Z=>” for simplifying creating hashes from computed lists.
By the way, since you want array indices for hash values and array values for hash keys, you could get the same results thus:
my %hash = @array.kv.reverse;
Or just:
my %hash = @array.kv.reverse;
Or just my %hash = @array.antipairs;