Quick Tip #5: The Z=> zip operator, lazy ranges, and terse hash creation.

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 .. *;

6 comments

  1. 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 🙂

    $ 6 'my @a = <a b c d e>; my %h = @a Z=> 0..*; dd %h'
    Hash %h = {:a(0), :b(1), :c(2), :d(3), :e(4)}
    
  2. 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;

Leave a Reply to TimToady Cancel reply

Your email address will not be published. Required fields are marked *