Firma senza slurping

Sep 08 2020

Questa è una domanda sul codice che già funziona! Ho molte subroutine che accettano più array come input, come ad esempio:

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;
    }

... che posso chiamare semplicemente con

@baz = sumarr( @foo, @bar);

Non ho trovato alcun modo per sostituire il prototipo con le firme, o almeno aumentare il prototipo con una firma per snellire l'elenco degli argomenti. C'è ancora qualcosa che lo fa?

Risposte

2 tobyink Sep 09 2020 at 00:04

Le firme vengono decompresse @_in variabili lessicali che hanno come ambito la funzione. I prototipi influenzano il modo in cui vengono analizzate le chiamate alla funzione . Quindi fanno cose diverse: non puoi semplicemente sostituire l'uno con l'altro. (Puoi scrivere una funzione che ha entrambi però.)

Un'illustrazione dei prototipi che influenzano l'analisi.

use strict;
use warnings;
use Data::Dumper;

my @a = ( 1 );
my @b = ( 2 );

myfunc( @a, @b );

sub myfunc (\@\@) {
    print Dumper( @_ );
}

myfunc( @a, @b );

Si noti che myfuncviene chiamato due volte con gli stessi argomenti, ma produce output diversi. Con use warnings, Perl ti avverte almeno che stai facendo qualcosa di potenzialmente strano.

Come ho già detto, è possibile dichiarare sia una firma che un prototipo per la stessa funzione.

sub myfunc ( $A, $B ) :prototype(\@\@) {
    print Dumper( @_ );
}

(Le firme sono ancora sperimentali e credo che di recente abbiano cambiato l'ordine di dichiarazione della firma e del prototipo! Un motivo per fare attenzione alle funzionalità sperimentali.)

TLDR: non puoi sostituire i prototipi con le firme, perché sono cose diverse.