Прототип: вернуть либо массив, либо скаляр
У меня проблемы с пониманием того, как вернуть массив с помощью прототипа подпрограммы. Вот пример
sub f (&@) {
my ($func) = @_;
eval &$func;
}
my $a = f {return 1};
my @b = f {return (2,1,1,4)};
print "a = ".$a."\n";
print "b = ".scalar(@b)."\n";
Это выводы a = 1
а также b = 1
, но я ожидаю @b
иметь длину четыре.
Я также пытался вернуть ссылку \ eval &$func
в функции f
, Я могу тогда разыменовать скаляр ($$a
1), но при разыменовании массива (@$b
) Perl говорит мне, что это не ссылка на массив.
2 ответа
Прототипы не влияют на то, возвращает ли подпрограмма скаляр или список. использование wantarray
если вы хотите знать, в каком контексте была вызвана подпрограмма.
eval &$func;
В строке выше сначала вызывается подпрограмма, на которую ссылается $func
в скалярном контексте затем преобразует свое возвращаемое значение в строку и выполняет эту строку как программу Perl.
sub f (&) {
my ($func) = @_;
eval { &$func }
}
Это будет делать то, что вы, очевидно, хотите (вызвать подпрограмму, на которую ссылается $func
в том же контексте (скаляр или список), в котором f
сам был назван, в пределах eval
блок для отлова ошибок во время выполнения).
sub f (&) {
my ($func) = @_;
eval { $func->(@_) }
}
Это более современный стиль, с ->
оператор.
Не нужно оценивать, вы можете
use warnings;
sub f (&) {
my ($func) = @_;
$func->(); # better than &$func
}
eval
с другой стороны, возвращает только последний элемент в списке, заданном $f
как то же самое, что писать eval scalar $func->();
, так @b
заканчивается одним элементом => 4
возвращаемое значение EXPR анализируется и выполняется, как если бы это была небольшая Perl-программа. Значение выражения (которое само определяется в скалярном контексте) сначала анализируется, и, если ошибок не было, выполняется как блок в лексическом контексте текущей программы Perl.