perlsub states the following:
When using a signature, the arguments are still available in the special array variable @_ , in addition to the lexical variables of the signature.
We can confirm this:
sub baz ($this, $that) {
warn '@_ contains ', scalar(@_), " elements.\n";
}
baz('hello', 'world') # @_ contains 2 elements.
But what happens when one of the parameters is optional?
sub foo ($this, $that = 'world') {
warn '@_ contains ', scalar(@_), " elements.\n";
}
foo('hello'); # @_ contains 1 elements.
Here's an example with tests:
#!/usr/bin/env perl
use strict;
use warnings;
use feature qw(signatures);
no warnings qw(experimental::signatures);
use Test::More tests => 8;
sub baz($this, $that) {
ok defined($this), "\$this is defined and contains $this";
ok defined($that), "\$that is defined and contains $that";
is scalar(@_), 2, '@_ has two elements.';
is_deeply \@_, [$this, $that]
or diag 'Parameters: ', explain {
this => $this,
that => $that,
at_underscore => \@_
};
}
sub foo ($this, $that='bar') {
ok defined($this), "\$this is defined and contains $this";
is $that, 'bar', '\$that contains "bar"';
is scalar(@_), 2, '@_ has two elements.';
is_deeply \@_, [$this, $that]
or diag 'Parameters: ', explain {
this => $this,
that => $that,
at_underscore => \@_
};
}
note "\n\nTesting baz()";
baz('hello', 'world');
note "\n\nTesting foo()";
foo("a");
The output is...
1..8
#
#
# Testing baz()
ok 1 - $this is defined and contains hello
ok 2 - $that is defined and contains world
ok 3 - @_ has two elements.
ok 4
#
#
# Testing foo()
ok 5 - $this is defined and contains a
ok 6 - \$that contains "bar"
not ok 7 - @_ has two elements.
# Failed test '@_ has two elements.'
# at mytest2.pl line 24.
# got: '1'
# expected: '2'
not ok 8
# Failed test at mytest2.pl line 25.
# Structures begin differing at:
# $got->[1] = Does not exist
# $expected->[1] = 'bar'
# Parameters: {
# 'at_underscore' => [
# 'a'
# ],
# 'that' => 'bar',
# 'this' => 'a'
# }
# Looks like you failed 2 tests of 8.
shell returned 2
This has probably been discussed a lot somewhere.
The question: Is the reason that scalar(@_) does not contain aliases to optional values so that we can determine how many parameters were actually passed, and if so, should it be documented?