子例程参数为没有临时变量的键值对

时间:2016-01-24 00:41:45

标签: perl hash subroutine subroutine-prototypes

在Perl中,我一直都喜欢参数传递的键值对样式,

fruit( apples => red );

我做了很多:

sub fruit {
    my %args = @_;
    $args{apples}
}

纯粹为了紧凑而且有多种方法可以做到这一点,有没有办法:

  • 访问键值对而不将@_分配给哈希?即在一个声明中?

  • 让子程序的参数自动成为哈希引用,也许是通过子程序原型?

无:

  • 分配给临时变量my %args = @_;

  • 让来电者通过引用传递,fruit({ apples => red }); 纯粹是为了美学


尝试

  • ${%{\@_}}{apples}

    尝试引用@_,将其解释为哈希引用,并按键访问值。

    但是我得到一个错误,它不是哈希引用。 (这不是' t ^。^)我想到C,你可以在其中投射指针,并避免明确的重新分配。

  • 我也尝试了子程序原型

    sub fruit (%) { ... }

    ...但是参数会像往常一样折叠成@_

2 个答案:

答案 0 :(得分:7)

您无法在没有哈希的情况下执行哈希查找(${...}{...})。但是你可以创建一个匿名哈希。

my $apples  = ${ { @_ } }{apples};
my $oranges = ${ { @_ } }{oranges};

您还可以使用更简单的取消引用语法

my $apples  = { @_ }->{apples};
my $oranges = { @_ }->{oranges};

但这会非常低效。您正在为每个参数创建新的哈希。这就是通常使用命名散列的原因。

my %args = @_;
my $apples  = $args{apples};
my $oranges = $args{oranges};

然而,另一种方法是使用散列片。

my ($apples, $oranges) = @{ { @_ } }{qw( apples oranges )};

以下是de-derefence版本,但它仅适用于5.24+ [1]

my ($apples, $oranges) = { @_ }->@{qw( apples oranges )};
  1. 如果您使用以下内容,则可在5.20+中使用:

    use feature qw( postderef );
    no warnings qw( experimental::postderef );
    

答案 1 :(得分:4)

如果你更关心紧凑性而不是效率,你可以这样做:

sub fruit {
    print( +{@_}->{apples}, "\n" );

    my $y = {@_}->{pears};

    print("$y\n");
}

fruit(apples => 'red', pears => 'green');

使用+{@_}->{apples}代替{@_}->{apples}的原因是它与print BLOCK LIST print语法没有它(或其他一些消除歧义的方法)冲突。