[Update: Perl v5.24 removes this experimental feature]
There’s a significant change in syntax showing up in Perl 5.14. The array operators push, pop, shift, and unshift previously only worked on named arrays or dereferenced references. Now, thanks to David Golden, they’ll work on array references. Not only that, they’ll work on references that you’ve stored in variables or that come as the return values from subroutine calls. This feature will show up in Perl 5.13.7, so you need to compile a development version to try this:
my $ref = [ qw(Buster Mimi Ginger Ella) ]; sub get_dogs { [ qw(Nicki Addy) ] } push $ref, 'Addy'; print "Pets are @$ref\n"; my $dog = shift get_dogs(); print "Dog is $dog\n";
This brings some Perl 6 ideas into Perl 5: where you can use an array, you can use things that act like arrays. This blurs the difference between a named array and a reference to it so Perl has even more DWIMery.
As of today, you have to compile the latest version of blead to try out this feature:
$ blead arrays2.pl Pets are Buster Mimi Ginger Ella Addy Dog is Nicki
Prior to Perl 5.14, perl would catch these errors at compile-time and tell you what it found and what it expected:
% perl5.12.2 array_operators.pl Type of arg 1 to push must be array (not private variable) at arrays.pl line 5, near "'Addy';" Type of arg 1 to shift must be array (not subroutine entry) at arrays.pl line 8, near ");" Execution of arrays.pl aborted due to compilation errors.
The fix to this, you have to use the ungainly deferencing syntax:
my $ref = [ qw(Buster Mimi Ginger Ella) ]; sub get_dogs { [ qw(Nicki Addy) ] } push @$ref, 'Addy'; print "Pets are @$ref\n"; my $dog = shift @{ get_dogs() }; print "Dog is $dog\n";
It’s ugly, but it works:
$ perl5.12.2 arrays2.pl Pets are Buster Mimi Ginger Ella Addy Dog is Nicki
If you want to get rid of the uglies, get ready to upgrade to Perl 5.14.
Thank you for your helpful posting, always.
Is this change applied to other array operators, like “sort”, “reverse”, “splice”, etc. ?
I know that splice is also fixed, but I’m not sure about the others (I guess I could just try it and find out :) reverse() is a tougher nut because it is not just an array operator, although Larry once told me that he can’t remember why he thought a scalar version was ever a good idea.
Here’s the relevant entry from the the perl git log:
I think it would be sweet to teach
map
andgrep
to accept an arrayref and return an arrayref. So:becomes
Just wondering: when $ref is an arrayref, will
be the same as
The scalar() built-in isn’t an array operator, so this doesn’t apply to it. However, you can always just try it yourself and find out, as well as checking the documentation for scalar(). :)
The problem is that
map
andgrep
operate on lists, whereaspush
,pop
, etc., operate on arrays or dereferenced arrayrefs. An array may be used when a list is expected but not the other way around. It’s relatively easy to allow arrayrefs when you previously only accepted arrays. However, a list passed tomap
orgrep
could be a list of arrayrefs and it might only have one element: a single arrayref. In that case, auto-dereferencing would iterate over a value that was never intended to be used in that way, causing errors that would be hard to catch.