perlhashsubroutinesubroutine-prototypes

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:

Without:


Attempted


Solution

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