perlsignaturesubroutine-prototypes

Signature without slurping


This is a question about code that already works! I have lots subroutines that take multiple arrays as inputs, such as:

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

...which I can call simply with

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

I haven't found any way to either replace the prototype with signatures, or at least augment the prototype with a signature for streamlining the argument list. Is there anything that does that yet?


Solution

  • Signatures unpack @_ into lexical variables which are scoped to within the function. Prototypes affect how calls to the function are parsed. So they do different things — you can't just replace one with the other. (You can write a function that has both though.)

    An illustration of prototypes affecting parsing.

    use strict;
    use warnings;
    use Data::Dumper;
    
    my @a = ( 1 );
    my @b = ( 2 );
    
    myfunc( @a, @b );
    
    sub myfunc (\@\@) {
        print Dumper( @_ );
    }
    
    myfunc( @a, @b );
    

    Notice that myfunc gets called twice with the same arguments, yet produces different outputs. With use warnings, Perl will at least warn you that you're doing something potentially weird.

    As I mentioned, it is possible to declare both a signature and a prototype for the same function.

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

    (Signatures are still experimental, and I believe that they did recently switch the order the signature and prototype are declared! A reason to beware experimental features.)

    TLDR: you can't replace prototypes with signatures, because they're different things.