Reputation: 958
In Perl, I've always liked the key-value pair style of argument passing,
fruit( apples => red );
I do this a lot:
sub fruit {
my %args = @_;
$args{apples}
}
Purely for compactness and having more than one way to do it, is there a way to either:
access the key-value pairs without assigning @_
to a hash? I.e. in a single statement?
have the subroutine's arguments automatically become a hash reference, perhaps via a subroutine prototype?
assigning to a temp variable my %args = @_;
having the caller pass by reference i.e. fruit({ apples => red });
purely for aesthetics
${%{\@_}}{apples}
Trying to reference @_
, interpret that as a hash ref, and access a value by key.
But I get an error that it's not a hash reference. (Which it isn't ^.^ ) I'm thinking of C where you can cast pointers, amongst other things, and avoid explicit reassignment.
I also tried subroutine prototypes
sub fruit (%) { ... }
...but the arguments get collapsed into @_
as usual.
Upvotes: 6
Views: 584
Reputation: 385829
You can't perform a hash lookup (${...}{...}
) without having a hash. But you could create an anonymous hash.
my $apples = ${ { @_ } }{apples};
my $oranges = ${ { @_ } }{oranges};
You could also use the simpler post-dereference syntax
my $apples = { @_ }->{apples};
my $oranges = { @_ }->{oranges};
That would be very inefficient though. You'd be creating a new hash for each parameter. That's why a named hash is normally used.
my %args = @_;
my $apples = $args{apples};
my $oranges = $args{oranges};
An alternative, however, would be to use a hash slice.
my ($apples, $oranges) = @{ { @_ } }{qw( apples oranges )};
The following is the post-derefence version, but it's only available in 5.24+[1]:
my ($apples, $oranges) = { @_ }->@{qw( apples oranges )};
It's available in 5.20+ if you use the following:
use feature qw( postderef );
no warnings qw( experimental::postderef );
Upvotes: 7
Reputation: 41872
If you're more concerned about compactness than efficiency, you can do it this way:
sub fruit {
print( +{@_}->{apples}, "\n" );
my $y = {@_}->{pears};
print("$y\n");
}
fruit(apples => 'red', pears => 'green');
The reason +{@_}->{apples}
was used instead of {@_}->{apples}
is that it conflicts with the print BLOCK LIST
syntax of print
without it (or some other means of disambiguation).
Upvotes: 4