Assinatura sem engolir
Essa é uma pergunta sobre código que já funciona! Tenho muitas sub-rotinas que usam vários arrays como entradas, como:
use 5.24.0;
use feature 'refaliasing';
no warnings "experimental::refaliasing";
my (@foo,@bar,@baz);
sub sumarr (\@\@);
# other code to load arrays
sub sumarr (\@\@)
{ my (@sum, @aa, @ab);
(\@aa,\@ab)=@_;
$sum[$_] = $aa[$_] + $ab[$_] for 0 .. $#aa;
return @sum;
}
... que posso chamar simplesmente com
@baz = sumarr( @foo, @bar);
Eu não encontrei nenhuma maneira de substituir o protótipo por assinaturas, ou pelo menos aumentar o protótipo com uma assinatura para simplificar a lista de argumentos. Existe alguma coisa que já faz isso?
Respostas
As assinaturas são descompactadas @_em variáveis lexicais cujo escopo é dentro da função. Protótipos afetam como as chamadas para a função são analisadas . Então, eles fazem coisas diferentes - você não pode simplesmente substituir um pelo outro. (Você pode escrever uma função que tenha ambos).
Uma ilustração de protótipos que afetam a análise.
use strict;
use warnings;
use Data::Dumper;
my @a = ( 1 );
my @b = ( 2 );
myfunc( @a, @b );
sub myfunc (\@\@) {
print Dumper( @_ );
}
myfunc( @a, @b );
Observe que myfuncé chamado duas vezes com os mesmos argumentos, mas produz saídas diferentes. Com use warnings, Perl irá pelo menos avisá-lo que você está fazendo algo potencialmente estranho.
Como mencionei, é possível declarar uma assinatura e um protótipo para a mesma função.
sub myfunc ( $A, $B ) :prototype(\@\@) {
print Dumper( @_ );
}
(As assinaturas ainda são experimentais e acredito que eles mudaram recentemente a ordem em que a assinatura e o protótipo são declarados! Um motivo para ter cuidado com os recursos experimentais.)
TLDR: você não pode substituir protótipos por assinaturas, porque são coisas diferentes.