Аргументы подпрограммы как пары ключ-значение без переменной temp

в Perl мне всегда нравился стиль пары ключ-значение передачи аргументов,

fruit( apples => red );

Я делаю это много:

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

чисто для компактности и имея более одного способа сделать это, есть ли способ либо:

  • доступ к парам ключ-значение без назначения @_ в хэш? Т. е. в одном заявлении?

  • аргументы подпрограммы автоматически становятся хэшем ссылка, возможно, через прототип подпрограммы?

без:

  • присвоение переменной temp my %args = @_;

  • наличие вызывающего абонента по ссылке, т. е. fruit({ apples => red }); чисто для эстетики


попытка

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

    попытка ссылки @_, интерпретировать, что в качестве хэш-реф, и доступ к значению по ключу.

    но я получаю ошибку, что это не хэш-ссылка. (А это не так ^.^ ) Я думаю о C, где вы можете бросить указатели, среди прочего, и избежать явного переназначения.

  • Я также пробовал прототипы подпрограмм

    sub fruit (%) { ... }

    ...но аргументы рушатся в @_ как обычно.

2 ответов


вы не можете выполнить хэш-функция lookup (${...}{...}) без хэша. Но вы можете создать анонимный хэш.

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

вы также можете использовать более простой синтаксис post-dereference

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

это было бы очень неэффективно. Вы создадите новый хэш для каждого параметра. Вот почему обычно используется именованный хэш.

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

альтернативой, однако, было бы использовать хэш-срез.

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

следующий версия post-derefence, но она доступна только в 5.24+[1]:

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

  1. он доступен в 5.20+, если вы используете следующее:

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

если вы больше обеспокоены компактностью, чем эффективностью, вы можете сделать это следующим образом:

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

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

    print("$y\n");
}

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

причина +{@_}->{apples} вместо {@_}->{apples} это то, что он конфликтует с print BLOCK LIST синтаксис print без него (или каких-либо других средств устранения неоднозначности).