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.
Passing Arguments to a Subroutine You can pass various arguments to a subroutine like you do in any other programming language and they can be acessed inside the function using the special array @_. Thus the first argument to the function is in $_[0], the second is in $_[1], and so on.
To pass parameters to a subroutine, the calling program pushes them on the stack in the reverse order so that the last parameter to pass is the first one pushed, and the first parameter to pass is the last one pushed. This way the first parameter is on top of the stack and the last one is at the bottom of the stack.
A Perl function or subroutine is a group of statements that together perform a specific task. In every programming language user want to reuse the code. So the user puts the section of code in function or subroutine so that there will be no need to write code again and again.
@ is used for an array. In a subroutine or when you call a function in Perl, you may pass the parameter list. In that case, @_ is can be used to pass the parameter list to the function: sub Average{ # Get total number of arguments passed. $ n = scalar(@_); $sum = 0; foreach $item (@_){ # foreach is like for loop...
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 );
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With