Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Subroutine arguments as key-value pairs without a temp variable

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?

Without:

  • assigning to a temp variable my %args = @_;

  • having the caller pass by reference i.e. fruit({ apples => red }); purely for aesthetics


Attempted

  • ${%{\@_}}{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.

like image 741
iPherian Avatar asked Jan 24 '16 00:01

iPherian


People also ask

How do you pass arguments to a subroutine in Perl?

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.

How do you pass a parameter to a subroutine?

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.

What is subroutine in Perl explain passing agreements to subroutine?

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.

What does @_ mean in Perl?

@ 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...


2 Answers

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 )};

  1. It's available in 5.20+ if you use the following:

    use feature qw( postderef );
    no warnings qw( experimental::postderef );
    
like image 163
ikegami Avatar answered Sep 25 '22 17:09

ikegami


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).

like image 25
cdlane Avatar answered Sep 24 '22 17:09

cdlane