Assinatura sem engolir

Sep 08 2020

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

2 tobyink Sep 09 2020 at 00:04

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.