Как я должен изменить прототип, чтобы разрешить создание хэша после coderef? - PullRequest
9 голосов
/ 16 декабря 2011

Вот что у меня есть:

use 5.14.0;
use strict;
use warnings;

sub my_func(&$) {
    my $coderef = shift;
    my %attribs = @_;
}

Вот чего я бы хотел достичь:

my_func {
    print 1;
} first_attrib => "1",second_attrib => "2";

Однако я получаю сообщение об ошибке Too many arguments for main::my_func at x.pl line 12, near ""2";". Как мне изменить прототип, чтобы параметры после coderef были преобразованы в хеш?

Ответы [ 2 ]

8 голосов
/ 16 декабря 2011

Если вы измените sub my_func(&$) на sub my_func(&%), ваш код будет работать.

Проблема в том, что first_attrib => "1",second_attrib => "2" - не хэш-ссылка, а список. И, как указал Фридо, список может быть назначен хешу, хотя список с нечетным числом элементов может привести к нежелательным результатам и выдаст предупреждение с use warnings.

В качестве альтернативы вы можете изменить свой код на

sub my_func(&$) {
    my $coderef = shift;
    my ($attribs) = @_;
}

my_func {
    print 1;
} {first_attrib => "1",second_attrib => "2"};

чтобы достичь того, чего вы, кажется, хотите.

Причина, по которой вы должны обернуть $attribs в паренах, заключается в том, что присвоение массива скаляру возвращает только количество элементов в массиве. На данный момент @_ это массив:

({first_attrib => "1",second_attrib => "2"})

с хэш-ссылкой в ​​качестве одного элемента.

($attribs) = @_;

указывает perl создать анонимный массив со скалярным $attribs в качестве первого элемента и присваивать элементы из @_ анонимному массиву, элемент за элементом, таким образом делая $attribs точку в хэш-ссылке в @_.

3 голосов
/ 16 декабря 2011

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

#!/usr/bin/env perl

use 5.14.0;
use strict;
use warnings;

sub my_func(&@) {
    my $coderef = shift;
    my %attribs = @_;
    $coderef->() for keys %attribs;
}

my_func {
    print 1;
} first_attrib => "1",second_attrib => "2";
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...