Home > other >  Perl 5 signatures: Passing multiple arrays
Perl 5 signatures: Passing multiple arrays

Time:01-03

I was hoping that with the signatures feature in Perl 5 (e.g. in version 5.34.0), something like this would be possible:

use feature qw{ say signatures };

&test(1, (2,3,4), 5, (6,7,8));

sub test :prototype($@$@) ($a, @b, $c, @d) {
    say "c=$c";
};

Or perhaps this:

sub test :prototype($\@$@) ($a, \@b, $c, @d) {
}

(as suggested here: https://www.perlmonks.org/?node_id=11109414).

However, I have not been able to make that work. My question is: With the signatures feature, is it possible to pass more than one array to a subroutine?

Alternatively: Even with signatures, is the only way to pass arrays by reference? That is to say: Are there any alternatives to passing by reference, e.g.:

sub test($a, $b, $c, @d) {
  my @b = @{$b};
}

Many thanks!

(P.S.: If there's a solution for arrays, then there'd be one for hashes as well, so I haven't spelled that out above.)

CodePudding user response:

With the signatures feature, is it possible to pass more than one array to a subroutine?

Yes you can do this:

use v5.22.0;   # experimental signatures requires perl >= 5.22
use feature qw(say);
use strict;
use warnings;
use experimental qw(signatures);

sub test :prototype($\@$\@) ($a, $b, $c, $d) {
    say "c=$c";
}

my @q  = (2,3,4);
my @r  = (6,7,8);
test(1, @q, 5, @r);

Output:

c=5

CodePudding user response:

As per suggestion in comment thread, summarising some of the ideas in a separate answer:

Proposed solution by Håkon Hægland

sub test :prototype($\@$\@) ($a, $b, $c, $d) {
    say "c=$c";
    say @$b;
}

my @q  = (2,3,4);
my @r  = (6,7,8);
test(1, @q, 5, @r);

The usual pass-by-reference

Note that this is different from traditional pass by reference:

my @q  = (2,3,4);
my @r  = (6,7,8);

sub test1 :prototype($$$$) ($a, $b, $c, $d) {
    say "c=$c";
    say @$b;
}

test1(1, \@q, 5, \@r);

Håkon's solution has the benefit of validation (and means that args are passed as @b rather than \@b).

Improvement with declared_refs

Diab Jerius suggested declared_refs, which is offers alternative syntax:

use v5.22.0;
use feature qw(say);
use strict;
use warnings;
use experimental qw(signatures declared_refs);

sub test :prototype($\@$\@) ($a, $b, $c, $d) {
    say "c=$c";
    say @$b;
    my \@bb = $b;
    say @bb;
}

What I (original poster) had hoped.

I was hoping that (mainly for optics) this would be possible

sub test :prototype($@$@) ($a, @b, $c, @d) {
    say @b;
};
  • Related