Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

sub signatures - too many arguments

25 views
Skip to first unread message

Peter Martini

unread,
Oct 22, 2012, 10:37:03 PM10/22/12
to Ruslan Zakirov, Perl 5 Porters
A separate thread for an important question - what should the following do:
sub foo($bar,$baz) {}
foo(1,2,3);
  
For the case with too many arguments and a non-greedy final (the above), I think the two real options are:
 
1. Make it die.  I understand there's a parallel between my ($a,$b) = (1,2,3), but the primary difference between the two is the 'my' declaration is strictly under the control of the author, while in the case of a sub, there's a clear distinction between the author of the sub and the callers.  The ${^ARGS_CNT} gets us at least a way to see if it was called with too many parameters, but what if the writer of the sub wanted it to die and complain with what the args are?  I'd rewritten parts of mktables with the new syntax as a way to find any bugs, and it does this as an integrity check.
 
2. Make it warn.  That would shift the burden from the callee to the caller, which may actually fit better with the language as a whole: as a writer of the sub, it shouldn't matter to me if they give me something I can't use, and as the user of the sub, I can turn on the warning or make it fatal to my hearts content.  The ban on @_ is a guarantee that if the sub was declared with 3 parameters, it will only use those 3, so using extra parameters does not actually affect the writer of the sub.
 
(or 3, ignore it - are there any takers in favor of silently ignoring?)
 
Option number one gives more control to the writer of the sub, option number two to the user.  Number 2 seems the most sensible to me, since this is strictly an error on the part of the caller and can't change the behavior of the callee.
 
It's late, and I've rewritten pieces of this several times, so I'm no longer sure its coherent.  Sending anyway, I hope I've gotten the essential distinction down.

Steffen Mueller

unread,
Oct 23, 2012, 1:17:39 AM10/23/12
to Peter Martini, Ruslan Zakirov, Perl 5 Porters
On 10/23/2012 04:37 AM, Peter Martini wrote:
> A separate thread for an important question - what should the following do:

> sub foo($bar,$baz) {}
> foo(1,2,3);

> For the case with too many arguments and a non-greedy final (the
> above), I think the two real options are:

> 1. Make it die.
[...]
> 2. Make it warn.

> (or 3, ignore it - are there any takers in favor of silently ignoring?)
> Option number one gives more control to the writer of the sub, option
> number two to the user. Number 2 seems the most sensible to me, since
> this is strictly an error on the part of the caller and can't change the
> behavior of the callee.

Sorry to say so, but I think 2) is the worst. It means that the
flexibility of ignoring the extra arguments is gone (shouldn't ignore a
warning) and doesn't provide the benefit of raising an exception at
invalid use.

I was never much of a proponent of the (LIST) = @_ argument, so I'd
favour 1) over 3), but still 3) over 2).

--Steffen

Salvador Fandino

unread,
Oct 23, 2012, 3:51:52 AM10/23/12
to Peter Martini, Ruslan Zakirov, Perl 5 Porters
On 10/23/2012 04:37 AM, Peter Martini wrote:
IMO, 1 is the most useful

Ed Avis

unread,
Oct 23, 2012, 4:27:14 AM10/23/12
to perl5-...@perl.org
Peter Martini <petercmartini <at> gmail.com> writes:

>sub foo($bar,$baz) {}
>foo(1,2,3);  

>I think the two real options are:
>  
>1. Make it die.  I understand there's a parallel between my ($a,$b) = (1,2,3),

FWIW, I would prefer that to die too, as in Python. It would eliminate a lot
of boilerplate checking when breaking a list into a fixed number of scalars.
Too late to change it now, of course...

>2. Make it warn.

>(or 3, ignore it - are there any takers in favor of silently ignoring?)

(2) and (3) can be implemented on top of (1) if the sub's author thinks it a
good idea to allow extra arguments which do nothing. Very often, a warning is
the least bad option to let the programmer know about a likely mistake without
breaking existing code. And in Perl, 'abc' + 1 may not necessarily be a mistake,
since the language as originally designed allows it. But here you can choose the
semantics you want starting from scratch. So I suggest the simplest option is to
implement those semantics, and anything else is an error; no need to second-guess
what the programmer might have meant, or try to keep existing code running.

--
Ed Avis <e...@waniasset.com>

demerphq

unread,
Oct 23, 2012, 4:37:17 AM10/23/12
to Ed Avis, perl5-...@perl.org
Personally I really hate the idea of it dieing.

I have many time done something like:

for my $sub (@subs) {
$sub->(@args);
}

and relied on the fact that subs that take fewer args than are in
@args will happily ignore the additional ones I have passed in.

IMO for now it should not die or warn until we have a way to specify
the appropriate behavior.

Yves

--
perl -Mre=debug -e "/just|another|perl|hacker/"

H.Merijn Brand

unread,
Oct 23, 2012, 4:36:20 AM10/23/12
to perl5-...@perl.org
On Tue, 23 Oct 2012 08:27:14 +0000 (UTC), Ed Avis <e...@waniasset.com>
wrote:

> Peter Martini <petercmartini <at> gmail.com> writes:
>
> >sub foo($bar,$baz) {}
> >foo(1,2,3);  
>
> >I think the two real options are:
> >  
> >1. Make it die.  I understand there's a parallel between my ($a,$b) = (1,2,3),
>
> FWIW, I would prefer that to die too, as in Python. It would eliminate a lot
> of boilerplate checking when breaking a list into a fixed number of scalars.
> Too late to change it now, of course...

And I'm glad :)

Of course it should not die (in the parallel example. There is loads of
examples of valid code where you want to ignore the rest of the
arguments

my ($foo, $bar) = unpack "s*", $struct;

I'm only interested in the first two arguments

my ($foo, undef, $bar) = @_;

I'm only interested in the first and third argument. I'm *very* glad I
do not have to add extra undef's at the end here

With this new signature work, it is a new area without backward
compatibility issues.

> >2. Make it warn.

I'm a bit between 2 and 3

warn when use warnings is active

what is done on ignore? are the other arguments discarded or are they
stored as leftovers in @_ ?

> >(or 3, ignore it - are there any takers in favor of silently ignoring?)
>
> (2) and (3) can be implemented on top of (1) if the sub's author thinks it a
> good idea to allow extra arguments which do nothing. Very often, a warning is
> the least bad option to let the programmer know about a likely mistake without
> breaking existing code. And in Perl, 'abc' + 1 may not necessarily be a mistake,
> since the language as originally designed allows it. But here you can choose the
> semantics you want starting from scratch. So I suggest the simplest option is to
> implement those semantics, and anything else is an error; no need to second-guess
> what the programmer might have meant, or try to keep existing code running.
>


--
H.Merijn Brand http://tux.nl Perl Monger http://amsterdam.pm.org/
using perl5.00307 .. 5.17 porting perl5 on HP-UX, AIX, and openSUSE
http://mirrors.develooper.com/hpux/ http://www.test-smoke.org/
http://qa.perl.org http://www.goldmark.org/jeff/stupid-disclaimers/

demerphq

unread,
Oct 23, 2012, 4:41:33 AM10/23/12
to Ed Avis, perl5-...@perl.org
And maybe at some point we will have a way to get access to the rest
of the arguments without needing a formal variable specifier - IMO it
can be very convenient to be able to lazily process the arguments on
the stack without copying them all at the beginning.

Aaron Crane

unread,
Oct 23, 2012, 3:34:12 PM10/23/12
to demerphq, Ed Avis, perl5-...@perl.org
demerphq <deme...@gmail.com> wrote:
> On 23 October 2012 10:27, Ed Avis <e...@waniasset.com> wrote:
>> Peter Martini <petercmartini <at> gmail.com> writes:
>>>sub foo($bar,$baz) {}
>>>foo(1,2,3);
>>
>>>1. Make it die
>>>2. Make it warn
>>>3, ignore it

My instinctive response is to prefer option 1. I do take your point
about option 2 moving the control from the callee to the caller; that
does sound tempting. But I think I'm essentially always going to want
an exception for excess arguments, so having to say `use warnings
'all', FATAL => 'excess_arguments'` sounds like quite a lot of
boilerplate for what I'm expecting will be the common case in new,
careful code

>> (2) and (3) can be implemented on top of (1) if the sub's author thinks it a
>> good idea to allow extra arguments which do nothing.

I take it you mean this sort of thing:

sub foo($bar, $baz, @ignored) {}
sub foo($bar, $baz, @excess) { warn "..." if @excess }

> Personally I really hate the idea of it dieing.
>
> I have many time done something like:
>
> for my $sub (@subs) {
> $sub->(@args);
> }
>
> and relied on the fact that subs that take fewer args than are in
> @args will happily ignore the additional ones I have passed in.

Does the ability for callees to explicitly accept (and ignore) any
number of slurpy arguments accommodate your concern on this issue?

If not, would that change if there were a shorter way to say "allow
excess arguments", perhaps something like this?

sub foo($bar, $baz, @) {}

(FWIW, I believe Perl 6 allows that, too — providing just a sigil in a
signature, rather than an identifier, to indicate that the parameter
should be accepted, even though there's no name by which to access
it.)

> IMO for now it should not die or warn until we have a way to specify
> the appropriate behavior.

Do you have any suggestions for what those ways might look like?

--
Aaron Crane ** http://aaroncrane.co.uk/

Jesse Luehrs

unread,
Oct 23, 2012, 3:46:32 PM10/23/12
to Aaron Crane, demerphq, Ed Avis, perl5-...@perl.org
My issue is actually in the other direction. I basically never pass
extra arguments to subs (unless I'm actually going to use them in a
slurpy argument), but passing fewer arguments in order to allow for
defaults is something I do all the time. Having it not die on the
incorrect number of arguments still allows for things like
"sub foo ($bar, $baz) { $baz //= 'default'; ... }" without forcing us to
decide on semantics for defaults.

That said, if we do have a decent idea about how defaults should work,
I'd be okay with strict-by-default with the ability to set defaults in
the parameters.

Maybe this just means that strict-by-default is the right answer, and I
can write old-style subs if I need defaults until defaults are
implemented?

> If not, would that change if there were a shorter way to say "allow
> excess arguments", perhaps something like this?
>
> sub foo($bar, $baz, @) {}
>
> (FWIW, I believe Perl 6 allows that, too — providing just a sigil in a
> signature, rather than an identifier, to indicate that the parameter
> should be accepted, even though there's no name by which to access
> it.)

In any case, I do like the idea of unnamed sigils for allowing
unnamed parameters as well.

-doy

Aaron Crane

unread,
Oct 24, 2012, 6:02:00 AM10/24/12
to Jesse Luehrs, demerphq, Ed Avis, perl5-...@perl.org
Jesse Luehrs <d...@tozt.net> wrote:
> My issue is actually in the other direction. I basically never pass
> extra arguments to subs (unless I'm actually going to use them in a
> slurpy argument), but passing fewer arguments in order to allow for
> defaults is something I do all the time. Having it not die on the
> incorrect number of arguments still allows for things like
> "sub foo ($bar, $baz) { $baz //= 'default'; ... }" without forcing us to
> decide on semantics for defaults.

I wasn't considering optional arguments, but I agree that they're an
important use case.

> That said, if we do have a decent idea about how defaults should work,
> I'd be okay with strict-by-default with the ability to set defaults in
> the parameters.
>
> Maybe this just means that strict-by-default is the right answer, and I
> can write old-style subs if I need defaults until defaults are
> implemented?

I think that sounds like a good idea: we'd still have core signatures,
covering the most obvious use cases (required scalar arguments,
trailing slurpy array, trailing slurpy hash), and with enough
strictures to detect accidental misuse. As we reach consensus about
how to handle all the other use cases that have been brought up, the
core signature mechanism can be extended to cover those, too.

Alexander Hartmaier

unread,
Oct 24, 2012, 5:58:00 PM10/24/12
to Aaron Crane, Jesse Luehrs, demerphq, Ed Avis, perl5-...@perl.org
I've looked at how Perl 6 handles this in http://cloud.github.com/downloads/perl6/book/2012.05.23.a4.pdf but haven't found how they deal with the number of parameters not matching the signature.
Does anyone know how Perl 6 behaves?
perlito [1] doesn't warn or die if I pass more parameters than specified.
The specs [2] say that positional parameters are required per default and that "Passing the wrong number of required arguments to a normal subroutine is a fatal error.".

The more the Perl 5 sub signatures are equal to the Perl 6 ones the easier it will be to switch between the two languages.

[1] http://perlcabal.org/~fglock/perlito6.html
[2] http://perlcabal.org/syn/S06.html#Required_parameters

Eirik Berg Hanssen

unread,
Oct 24, 2012, 8:43:37 PM10/24/12
to Alexander Hartmaier, Aaron Crane, Jesse Luehrs, demerphq, Ed Avis, perl5-...@perl.org
On Wed, Oct 24, 2012 at 11:58 PM, Alexander Hartmaier <alex.ha...@gmail.com> wrote:
I've looked at how Perl 6 handles this in http://cloud.github.com/downloads/perl6/book/2012.05.23.a4.pdf but haven't found how they deal with the number of parameters not matching the signature.
Does anyone know how Perl 6 behaves?
perlito [1] doesn't warn or die if I pass more parameters than specified.
The specs [2] say that positional parameters are required per default and that "Passing the wrong number of required arguments to a normal subroutine is a fatal error.".

$ perl6
> sub f ($x, $y) { say "$x & $y" }
f
> f 1, 2;
1 & 2
> f 1, 2, 3;
Too many positional parameters passed; got 3 but expected 2
>

  Note however that the implicit/default signature is (*@_, *%_), a slurpy array for positional arguments and a slurpy hash for named arguments, to the extent the code actually accesses these parameters:

> sub g { say @_.join(" & ") }
g
> g 1, 2, 3;
1 & 2 & 3
> say &g.signature.perl
:(;; *@_)
> sub h { %_.keys.join(" & ").say; %_.values.join(" & ").say }
h
> h :a(1), :b(2);
a & b
1 & 2
> say &h.signature.perl
:(;; *%_)
>


Eirik

Peter Martini

unread,
Oct 24, 2012, 8:51:02 PM10/24/12
to Eirik Berg Hanssen, Alexander Hartmaier, Aaron Crane, Jesse Luehrs, demerphq, Ed Avis, perl5-...@perl.org
On Wed, Oct 24, 2012 at 8:43 PM, Eirik Berg Hanssen <Eirik-Ber...@allverden.no> wrote:
On Wed, Oct 24, 2012 at 11:58 PM, Alexander Hartmaier <alex.ha...@gmail.com> wrote:
I've looked at how Perl 6 handles this in http://cloud.github.com/downloads/perl6/book/2012.05.23.a4.pdf but haven't found how they deal with the number of parameters not matching the signature.
Does anyone know how Perl 6 behaves?
perlito [1] doesn't warn or die if I pass more parameters than specified.
The specs [2] say that positional parameters are required per default and that "Passing the wrong number of required arguments to a normal subroutine is a fatal error.".

$ perl6
> sub f ($x, $y) { say "$x & $y" }
f
> f 1, 2;
1 & 2
> f 1, 2, 3;
Too many positional parameters passed; got 3 but expected 2
>


Can you post what f 1; would look like?

Eirik Berg Hanssen

unread,
Oct 24, 2012, 8:59:21 PM10/24/12
to Peter Martini, Alexander Hartmaier, Aaron Crane, Jesse Luehrs, demerphq, Ed Avis, perl5-...@perl.org
On Thu, Oct 25, 2012 at 2:51 AM, Peter Martini <peterc...@gmail.com> wrote:
On Wed, Oct 24, 2012 at 8:43 PM, Eirik Berg Hanssen <Eirik-Ber...@allverden.no> wrote:
$ perl6
> sub f ($x, $y) { say "$x & $y" }
f
> f 1, 2;
1 & 2
> f 1, 2, 3;
Too many positional parameters passed; got 3 but expected 2
>



Can you post what f 1; would look like?

> f 1;
Not enough positional parameters passed; got 1 but expected 2


  And while I'm at it, an example with an optional parameter:

> sub F ($x, $y='<not passed>') { say "$x & $y" }
F
> F;
Not enough positional parameters passed; got 0 but expected between 1 and 2
> F 1;
1 & <not passed>
> F 1, 2;
1 & 2
> F 1, 2, 3;
Too many positional parameters passed; got 3 but expected between 1 and 2
>

  And, just for completeness, how it looks with a slurpy array:

> sub G ($x, *@y) { join(' & ', $x, @y).say }
G
> G;
Not enough positional parameters passed; got 0 but expected at least 1
> G 1;
1
> G 1, 2;
1 & 2
> G 1, 2, 3;

1 & 2 & 3
>


Eirik

Reini Urban

unread,
Oct 25, 2012, 10:40:59 AM10/25/12
to Steffen Mueller, Peter Martini, Ruslan Zakirov, Perl 5 Porters
On Tue, Oct 23, 2012 at 12:17 AM, Steffen Mueller <smue...@cpan.org> wrote:
> On 10/23/2012 04:37 AM, Peter Martini wrote:
>>
>> A separate thread for an important question - what should the following
>> do:
>
>
>> sub foo($bar,$baz) {}
>> foo(1,2,3);
>
>
>> For the case with too many arguments and a non-greedy final (the
>> above), I think the two real options are:
>
>
>> 1. Make it die.
>> 2. Make it warn.
>> (or 3, ignore it - are there any takers in favor of silently ignoring?)

You forgot the most important option:
4. compile-time croak.

Of course 4 should be chosen, to enable compile-time strictness.
Deferring such declaration errors to run-time does not help the poor
user.
--
Reini Urban
http://cpanel.net/ http://www.perl-compiler.org/

Leon Timmermans

unread,
Oct 25, 2012, 10:46:14 AM10/25/12
to Reini Urban, Steffen Mueller, Peter Martini, Ruslan Zakirov, Perl 5 Porters
On Thu, Oct 25, 2012 at 4:40 PM, Reini Urban <rur...@x-ray.at> wrote:
> You forgot the most important option:
> 4. compile-time croak.
>
> Of course 4 should be chosen, to enable compile-time strictness.
> Deferring such declaration errors to run-time does not help the poor
> user.

How would you handle «foo(@bar)»? I don't think this possible in the
general case, even if it's sometimes possible.

Leon

Jesse Luehrs

unread,
Oct 25, 2012, 10:49:37 AM10/25/12
to Reini Urban, Steffen Mueller, Peter Martini, Ruslan Zakirov, Perl 5 Porters
It obviously can't be entirely a compile time check, without getting
into the parsing changes that make prototypes so terrible to deal with.
So starting as a runtime error should be fine, and if there are certain
special cases we can detect at compile time, we can certainly look into
adding that in later.

-doy

Peter Martini

unread,
Oct 25, 2012, 11:06:46 AM10/25/12
to Leon Timmermans, Ruslan Zakirov, Perl 5 Porters, Steffen Mueller, Reini Urban

Another examples Yves brought up:

for my $sub (@subs) {
   $sub->(@args);
}

Not even detectable in principle.

And die at compile time is part of number 1, if feasible.  Pardon me if that wasnt clear.

Eirik Berg Hanssen

unread,
Oct 25, 2012, 11:07:45 AM10/25/12
to Reini Urban, Steffen Mueller, Peter Martini, Ruslan Zakirov, Perl 5 Porters
On Thu, Oct 25, 2012 at 4:40 PM, Reini Urban <rur...@x-ray.at> wrote:

  4 cannot cover all cases.  foo(@bar) cannot be handled at compile time (... unless there is also a prototype ...), and so we need run-time handling.

  I'm leaning towards 1, with an optional 4 on the side.  SWYM, sub writers!


Eirik

Reini Urban

unread,
Oct 25, 2012, 11:19:57 AM10/25/12
to Eirik Berg Hanssen, Steffen Mueller, Peter Martini, Ruslan Zakirov, Perl 5 Porters
Of course @ and % ending parameters cannot be checked at all.
This is obvious.
They also cannot be checked at run-time. Lists can be empty.

So there's still 4 as only option I foresee.

Peter: die is always run-time, compile-time we call it croak.

> I'm leaning towards 1, with an optional 4 on the side. SWYM, sub writers!

Jesse Luehrs

unread,
Oct 25, 2012, 11:23:07 AM10/25/12
to Reini Urban, Eirik Berg Hanssen, Steffen Mueller, Peter Martini, Ruslan Zakirov, Perl 5 Porters
How can it not be checked at runtime? We can certainly do
"sub foo { die if @_ < 2; ... }" right now, and I don't see why that
logic couldn't be replicated in the signature logic.

> Peter: die is always run-time, compile-time we call it croak.

This is not true, I'm not sure where you get that impression.

-doy

Reini Urban

unread,
Oct 25, 2012, 11:30:24 AM10/25/12
to Jesse Luehrs, Eirik Berg Hanssen, Steffen Mueller, Peter Martini, Ruslan Zakirov, Perl 5 Porters
die is an op, (and as c call used in pp*.c, the run-time),
not used by the parser nor the compiler.
croak is a compile-time error used by the parser and compiler.

grep _die *.c
vs
grep _croak *.c

Jesse Luehrs

unread,
Oct 25, 2012, 11:50:00 AM10/25/12
to Reini Urban, Eirik Berg Hanssen, Steffen Mueller, Peter Martini, Ruslan Zakirov, Perl 5 Porters
croak can be used at runtime - it's just a normal part of the perl API
(it is in fact the underlying implementation of pp_die). It is also used
in XSUBs quite frequently (which are executed at runtime).

-doy

Reini Urban

unread,
Oct 25, 2012, 12:51:10 PM10/25/12
to Jesse Luehrs, Eirik Berg Hanssen, Steffen Mueller, Peter Martini, Ruslan Zakirov, Perl 5 Porters
Better: croak is used for compile-time errors, used by the parser and compiler.

>> grep _die *.c
>> vs
>> grep _croak *.c
>
> croak can be used at runtime - it's just a normal part of the perl API
> (it is in fact the underlying implementation of pp_die). It is also used
> in XSUBs quite frequently (which are executed at runtime).

That's true. croak can be called at run-time also

Aristotle Pagaltzis

unread,
Oct 25, 2012, 1:09:50 PM10/25/12
to perl5-...@perl.org
TL;DR: Some arity mismatch errors *can* be detected at compile time, and
those *should* be – eventually, it doesn’t have to be part of the
first iteration. Other arity mismatch errors *cannot* be detected
at compile time, and those necessarily will be runtime errors.

So this whole sub-thread is an unnecessary diversion.


* Reini Urban <rur...@x-ray.at> [2012-10-25 16:45]:
> On Tue, Oct 23, 2012 at 12:17 AM, Steffen Mueller <smue...@cpan.org> wrote:
> > On 10/23/2012 04:37 AM, Peter Martini wrote:
> >> For the case with too many arguments and a non-greedy final (the
> >> above), I think the two real options are:
> >>
> >> 1. Make it die.
> >> 2. Make it warn.
> >> (or 3, ignore it - are there any takers in favor of silently ignoring?)
>
> You forgot the most important option:
> 4. compile-time croak.

Compile time vs run time is completely orthogonal to Peter’s question,
which is whether too many arguments should be an error or not. If they
are, then obviously detecting them at compile time wherever possible is
preferable.


* Leon Timmermans <faw...@gmail.com> [2012-10-25 16:50]:
> How would you handle «foo(@bar)»? I don't think this possible in the
> general case, even if it's sometimes possible.

It is not possible in the general case, but it possible in plenty of
particular cases.

For an analogy, consider that the context of a function call is not
decidable in general case, yet in plenty of cases is already known at
compile time, in which case it is denoted in the optree.


* Jesse Luehrs <d...@tozt.net> [2012-10-25 16:55]:
> It obviously can't be entirely a compile time check, without getting
> into the parsing changes that make prototypes so terrible to deal with.

But it can be *partially* compile time without the horrors of prototypes.

> So starting as a runtime error should be fine, and if there are certain
> special cases we can detect at compile time, we can certainly look into
> adding that in later.

Yes.


* Reini Urban <rur...@x-ray.at> [2012-10-25 17:25]:
> Of course @ and % ending parameters cannot be checked at all.

This has nothing to do with trailing slurpy parameters. It has to do
with the fact that lists automatically flatten in Perl 5. `foo(@bar)`
will not call `foo` with a single argument, it will call it with any
number of arguments from zero to arbitrarily many.

If `foo` expects three scalar arguments and `@bar` is a three-element
array, then there is absolutely no reason for this to be an error at
runtime, much less a parse error. It is well possible that the code
which calls `foo` is constructing the argument list dynamically but
makes sure to always put the right number of arguments in it. The parser
has no business trying to decide whether the program is wrong in that
case.

In fact if it is made a parse error to do that, then these new
signatures will be even more useless to me than prototypes. (I can at
least use prototypes to allow a leading coderef to be passed without
writing `sub`! And I can use them to make constants. So I use them
*sometimes*.)

> So there's still 4 as only option I foresee.

The parser cannot know whether @bar will satisfy that invariant in all
cases unless you solve the halting problem.

So the error MUST be detected at runtime in at least SOME of the cases.
Not only is option 4 not the *only* option, but it cannot even be an
option in and of itself – in Perl 5, it can only be part of option 1.

For the first cut of the feature, error checking can be runtime-only.
That would be identical to the current state of things anyway: it *has
always been* runtime-only when people have done `die if @_ > $x`.


Regards,
--
Aristotle Pagaltzis // <http://plasmasturm.org/>

Aristotle Pagaltzis

unread,
Oct 25, 2012, 1:46:44 PM10/25/12
to perl5-...@perl.org
I have come to the following conclusions:


* Peter Martini <peterc...@gmail.com> [2012-10-23 04:40]:
> A separate thread for an important question - what should the following do:
> sub foo($bar,$baz) {}
> foo(1,2,3);

This should die.


* demerphq <deme...@gmail.com> [2012-10-23 10:40]:
> IMO for now it should not die or warn until we have a way to specify
> the appropriate behavior.

&foo(1,2,3) should not die.


— · & · —


Yves’ example shows my original suggestion that we could add syntax to
signatures to declare whether they should be strict or not was wrong:

> Personally I really hate the idea of it dieing.
>
> I have many time done something like:
>
> for my $sub (@subs) {
> $sub->(@args);
> }
>
> and relied on the fact that subs that take fewer args than are in
> @args will happily ignore the additional ones I have passed in.

It is actually the caller who needs to be able to decide whether a call
with too many arguments should die or not. Leaving the decision to the
callee would be nonsense.

We already have syntax to let the caller decide, in another case.

And it’s ugly, so people will want to avoid using it, and it will stand
out like a sore thumb to them when someone uses it. This is a feature.

Note that `$sub->(@args)` and `&$sub(@args)` are indistinguishable right
now. I propose that the parser remember this difference so that Yves
could write his example as the latter whereas the former would throw an
error if too many arguments were passed.

Hopefully this is feasible.

--
*AUTOLOAD=*_;sub _{s/::([^:]*)$/print$1,(",$\/"," ")[defined wantarray]/e;chop;$_}
&Just->another->Perl->hack;
#Aristotle Pagaltzis // <http://plasmasturm.org/>

demerphq

unread,
Oct 26, 2012, 3:06:12 AM10/26/12
to perl5-...@perl.org
I think this a fine solution. Thanks Aristotle.

The Sidhekin

unread,
Oct 27, 2012, 12:28:04 PM10/27/12
to demerphq, perl5-...@perl.org
On Fri, Oct 26, 2012 at 9:06 AM, demerphq <deme...@gmail.com> wrote:
> Personally I really hate the idea of it dieing.
>
> I have many time done something like:
>
> for my $sub (@subs) {
>    $sub->(@args);
> }
>
> and relied on the fact that subs that take fewer args than are in
> @args will happily ignore the additional ones I have passed in.

It is actually the caller who needs to be able to decide whether a call
with too many arguments should die or not. Leaving the decision to the
callee would be nonsense.

We already have syntax to let the caller decide, in another case.

And it’s ugly, so people will want to avoid using it, and it will stand
out like a sore thumb to them when someone uses it. This is a feature.

Note that `$sub->(@args)` and `&$sub(@args)` are indistinguishable right
now. I propose that the parser remember this difference so that Yves
could write his example as the latter whereas the former would throw an
error if too many arguments were passed.

I think this a fine solution. Thanks Aristotle.

  I think it's too subtle.

  Also, it's conflating disabling of prototype check (which never even happens with derefs) and disabling of arity check.

  Instead of piggybacking I'd rather see something explicitly disabling arity checks, for example:

for my $sub (@subs) {
    no strict 'arity';
    $sub->(@args);
}

  (Consider it an analogue of the 'refs' stricture, what with changing run-time behaviour.  But with little or no backwards compatibility to consider, we might even make it a stricture that's on by default, even before loading strict.pm.  Which in my world would be another parallel to 'refs', if that wasn't laden with backwards compatibility issues ...)


Eirik

Peter Martini

unread,
Oct 27, 2012, 12:47:56 PM10/27/12
to sidh...@allverden.no, demerphq, perl5-...@perl.org
+1

Aristotle Pagaltzis

unread,
Oct 27, 2012, 1:09:25 PM10/27/12
to perl5-...@perl.org
* The Sidhekin <sidh...@allverden.no> [2012-10-27 18:30]:
> I think it's too subtle.

Maybe. It’s at least plenty ugly.

> Also, it's conflating disabling of prototype check (which never even
> happens with derefs) and disabling of arity check.

Depends on how you look at it. Arity checks are necessarily runtime in
spirit (but optionally compile time); prototype checks are necessarily
compile time. So is this a conflation of two different functionalities,
or is it an extension of the same functionality?

I see your point; but to my eye this can be argued both ways.

> Instead of piggybacking I'd rather see something explicitly disabling
> arity checks, for example:
>
> for my $sub (@subs) {
> no strict 'arity';
> $sub->(@args);
> }
>
> (Consider it an analogue of the 'refs' stricture, what with changing
> run-time behaviour. But with little or no backwards compatibility to
> consider, we might even make it a stricture that's on by default, even
> before loading strict.pm. Which in my world would be another parallel
> to 'refs', if that wasn't laden with backwards compatibility issues
> ...)

I find this solution way too heavy and cumbersome, personally. So
I guess the question of the right level of subtlety is a matter of
taste.

However, I could live with it.

… up to the point where you propose that it be a stricture that is
enabled without explicit request. No other stricture works that way and
I do not believe the exception is even necessary, so let’s please not
add one. After all, `use 5.012` or higher will enable all strictures. So
whichever perl version enables these signatures by default could also
enable the stricture in the same version feature bundle. Problem solved.

Peter Martini

unread,
Oct 27, 2012, 2:17:09 PM10/27/12
to perl5-...@perl.org
On Sat, Oct 27, 2012 at 1:09 PM, Aristotle Pagaltzis <paga...@gmx.de> wrote:
* The Sidhekin <sidh...@allverden.no> [2012-10-27 18:30]:
> I think it's too subtle.

Maybe. It’s at least plenty ugly.

I actually like that syntax, but the interaction with traditional prototypes makes my head swim.  Especially when it comes to playing with array references, file globs, etc, or trying to extend it to object methods (can't just do &$obj->foo(1,2,3)).
So, effectively, strict by default (as a normal stricture), but with the option of turning it off with no strict?  It seems like this is a good philosophical fit with the rest of the language - enough rope to hang yourself with, if you insist, and strict to turn on/off the strictness.

I'll prototype it so we can see how it actually feels.

Eirik Berg Hanssen

unread,
Oct 27, 2012, 3:06:07 PM10/27/12
to perl5-...@perl.org
On Sat, Oct 27, 2012 at 7:09 PM, Aristotle Pagaltzis <paga...@gmx.de> wrote:
… up to the point where you propose that it be a stricture that is
enabled without explicit request. No other stricture works that way and
I do not believe the exception is even necessary, so let’s please not
add one. After all, `use 5.012` or higher will enable all strictures. So
whichever perl version enables these signatures by default could also
enable the stricture in the same version feature bundle. Problem solved.

  Well, except that the caller need not be in the same scope as the declaration, and so need not be in scope of any C<< use 5.012 >>, and won't get that stricture ...


  The thing with strictness is that the current three are cases of retrofitted strictness, and being retrofitted, backwards compatibility wants them off by default.  But for any new feature, strictness could be on by default.

  Now, if you do make a rule from those three, then the strict pragma is for retrofitted strictness only.  In order to drop strictness that is on by default, one would do something else.

  Use a different pragma, perhaps?

for my $sub (@subs) {
    use lax 'arity';
    $sub->(@args);
}

  Nah.  Enabling of laxity and disabling of strictness differ only in what the default is.  Useless distinction. :-\

  So, with that rules, perhaps a pragma is a wrong solution for bypassing arity checks.

for my $sub (@subs) {
    $sub->(@args[ 0..signature($sub)->arity-1 ]);
}

  Ugly.  But we have a need of introspection, and this falls out of it.

for my $sub (@subs) {
    $sub->(@args[ signature($sub)->positions ]); # for utility?
}

for my $sub (@subs) {
    signature($sub)->laxcall($sub, @args); # for even more utility?
}

  Better?

  I still think I prefer C<< no strict 'arity' >>, but the C<< signature($sub) >> object is intriguing.  I think we'll need something like it, and having it, a few utility methods couldn't do much harm ...


Eirik

Aristotle Pagaltzis

unread,
Oct 27, 2012, 4:08:29 PM10/27/12
to perl5-...@perl.org
* Eirik Berg Hanssen <Eirik-Ber...@allverden.no> [2012-10-27 21:10]:
> On Sat, Oct 27, 2012 at 7:09 PM, Aristotle Pagaltzis <paga...@gmx.de>wrote:
> > … up to the point where you propose that it be a stricture that is
> > enabled without explicit request. No other stricture works that way
> > and I do not believe the exception is even necessary, so let’s
> > please not add one. After all, `use 5.012` or higher will enable all
> > strictures. So whichever perl version enables these signatures by
> > default could also enable the stricture in the same version feature
> > bundle. Problem solved.
>
> Well, except that the caller need not be in the same scope as the
> declaration, and so need not be in scope of any C<< use 5.012 >>, and
> won't get that stricture ...

Actually now I am turned me off of the whole idea of implementing this
as a stricture. So old code is getting a stricture enabled on it that it
didn’t ask for explicitly, even when it hasn’t turned on any strictures?
Then what do you do with `no strict` in old code – does it disable the
new stricture? But the new stricture didn’t exist when that `no strict`
line was written. So does it leave it enabled? So then what does a bare
`use strict` do – does it enable it, or is it kept symmetric with the
`no strict` set?

There are no good answers to any of these questions, ergo `strict` is
the wrong place for this.

> Use a different pragma, perhaps?
>
> for my $sub (@subs) {
> use lax 'arity';
> $sub->(@args);
> }
>
> Nah. Enabling of laxity and disabling of strictness differ only in what
> the default is. Useless distinction. :-\

A single-purpose pragma would work. Something like `no aritycheck`.

> So, with that rules, perhaps a pragma is a wrong solution for bypassing
> arity checks.
>
> for my $sub (@subs) {
> $sub->(@args[ 0..signature($sub)->arity-1 ]);
> }
>
> Ugly. But we have a need of introspection, and this falls out of it.

I thought of this too. It seemed over-general for the problem at hand,
but it would provide a solution. (My thought was an `arity` function in
a new module Sub::Util, but same difference.)

> for my $sub (@subs) {
> $sub->(@args[ signature($sub)->positions ]); # for utility?
> }
>
> for my $sub (@subs) {
> signature($sub)->laxcall($sub, @args); # for even more utility?
> }
>
> Better?

I don’t like either. But if there was a Sub::Util the latter could be
a function that would come out something like this:

for my $sub (@subs) {
call $sub => @args;
}

(It may need a better name.)

With that, I can live.

> I still think I prefer C<< no strict 'arity' >>, but the C<<
> signature($sub) >> object is intriguing. I think we'll need something
> like it, and having it, a few utility methods couldn't do much harm
> ...

I was trying to avoid going there so soon… a full-blown introspection
interface that has room to expand to accommodate future additions to the
signature syntax is not going to be a simple job. I was hoping we could
wait to see what things people actually try to do which the lack of an
introspection interface prevents them from, so there would be experience
to inform its design instead, rather than creation in a vacuum.

Then again, the Sub::Util::call I proposed above would not depend on the
existence of an introspection interface, it could simply be part of the
signatures code in core, exposed by tiny bit of XS. Or maybe it’d live
in some new `sub::` namespace à la Yves’ mauve proposal.

Peter Martini

unread,
Oct 27, 2012, 4:37:14 PM10/27/12
to perl5-...@perl.org
On Sat, Oct 27, 2012 at 4:08 PM, Aristotle Pagaltzis <paga...@gmx.de> wrote:
* Eirik Berg Hanssen <Eirik-Ber...@allverden.no> [2012-10-27 21:10]:
> On Sat, Oct 27, 2012 at 7:09 PM, Aristotle Pagaltzis <paga...@gmx.de>wrote:
> > … up to the point where you propose that it be a stricture that is
> > enabled without explicit request. No other stricture works that way
> > and I do not believe the exception is even necessary, so let’s
> > please not add one. After all, `use 5.012` or higher will enable all
> > strictures. So whichever perl version enables these signatures by
> > default could also enable the stricture in the same version feature
> > bundle. Problem solved.
>
> Well, except that the caller need not be in the same scope as the
> declaration, and so need not be in scope of any C<< use 5.012 >>, and
> won't get that stricture ...

Actually now I am turned me off of the whole idea of implementing this
as a stricture. So old code is getting a stricture enabled on it that it
didn’t ask for explicitly, even when it hasn’t turned on any strictures?
Then what do you do with `no strict` in old code – does it disable the
new stricture? But the new stricture didn’t exist when that `no strict`
line was written. So does it leave it enabled? So then what does a bare
`use strict` do – does it enable it, or is it kept symmetric with the
`no strict` set?

There are no good answers to any of these questions, ergo `strict` is
the wrong place for this.


Are we generally agreed that strictness/laxness should be controllable by the caller, with strict as the default, and the lax behavior matching what I've already implemented?

If so, I'll least put the hooks in place internally, and stop contributing noise to the best way to turn on/off the feature :-)

I find both sides arguments persuasive, and it seems we're down to the best way to toggle the switch.

Aristotle Pagaltzis

unread,
Oct 27, 2012, 4:57:40 PM10/27/12
to perl5-...@perl.org
* Peter Martini <peterc...@gmail.com> [2012-10-27 22:40]:
> Are we generally agreed that strictness/laxness should be controllable
> by the caller, with strict as the default, and the lax behavior
> matching what I've already implemented?

I hope so but there is no way to know.

I have been wishing more people would chime in on this subthread.

Robert Sedlacek

unread,
Oct 27, 2012, 5:07:18 PM10/27/12
to perl5-...@perl.org
I would agree as well, but here are some thoughts:

- This would be a lexical switch, correct? Meaning it won't disable
strictness inside the called sub?

- The current proposal of 'arity' sounds like it would apply to
additional and missing arguments. While I'd personally be very happy
about that, it seems to me people might want default-missing-to-undef
instead.

regards,
--
Robert 'phaylon' Sedlacek

Perl 5 Consultant for
Shadowcat Systems Limited - http://shadowcat.co.uk/

Eirik Berg Hanssen

unread,
Oct 27, 2012, 5:10:38 PM10/27/12
to Peter Martini, perl5-...@perl.org
On Sat, Oct 27, 2012 at 10:37 PM, Peter Martini <peterc...@gmail.com> wrote:

Are we generally agreed that strictness/laxness should be controllable by the caller, with strict as the default, and the lax behavior matching what I've already implemented?

  The callee can declare laxness already, by adding a slurpy:

sub foo ($bar, $baz, @ignored) { ... }

  So I think strict should be the default, when the callee is not declared lax.

  As for whether this _should_ also be controllable by the caller, I'm not entirely sure.

  It is not necessary: With sufficient introspection, anyone could write a call function to do it, as Aristotle Pagaltzis suggested: C<< call $sub => @args >>.

  But I see no harm in it.  And it may be both clearer and faster if we don't make people use introspection to get to it.  :-)


Eirik

Peter Martini

unread,
Oct 27, 2012, 5:24:18 PM10/27/12
to Robert Sedlacek, perl5-...@perl.org
On Sat, Oct 27, 2012 at 5:07 PM, Robert Sedlacek <r...@474.at> wrote:
On Sat, 2012-10-27 at 22:57 +0200, Aristotle Pagaltzis wrote:
> * Peter Martini <peterc...@gmail.com> [2012-10-27 22:40]:
> > Are we generally agreed that strictness/laxness should be controllable
> > by the caller, with strict as the default, and the lax behavior
> > matching what I've already implemented?
>
> I hope so but there is no way to know.
>
> I have been wishing more people would chime in on this subthread.

I would agree as well, but here are some thoughts:

- This would be a lexical switch, correct? Meaning it won't disable
  strictness inside the called sub?


Absolutely.
 
- The current proposal of 'arity' sounds like it would apply to
  additional and missing arguments. While I'd personally be very happy
  about that, it seems to me people might want default-missing-to-undef
  instead.

I'd originally started this thread meaning for it to just cover the too many arguments case, but never split it off for the too few args case.  Too many args is purely the callers problem, since if the callee isn't intending to use the data anyway, it can't affect the operation of the sub.  Too few is a little sticky due to one of the logical progressions in signatures, defaults for arguments, that I've avoided touching like the plague :-)

The Sidhekin

unread,
Oct 27, 2012, 5:30:15 PM10/27/12
to perl5-...@perl.org
On Sat, Oct 27, 2012 at 9:06 PM, Eirik Berg Hanssen <Eirik-Ber...@allverden.no> wrote:
  So, with that rules, perhaps a pragma is a wrong solution for bypassing arity checks.

for my $sub (@subs) {
    $sub->(@args[ 0..signature($sub)->arity-1 ]);
}

  Eh, that one's necessarily lax also with respect to too few arguments, effectively padding the argument list with undefs.

  But ugh, of course that's not quite right.  The matter is not so simple, unless all parameters are mandatory.

  If there's a slurpy, we want to pass all of @args, if necessary padded with undefs to the minimum number of positionals.

  And if we ever get optional arguments, there could be a finite maximum different from the minimum.

  It would need to be something like this:

for my $sub (@subs) {
    my $min = signature($sub)->min;
    my $max = signature($sub)->max;
    $sub->(@args[ 0..( $max < @args ? $max-1 : $min > @args ? $min-1 : $#args ]);
}

 Yikes!


for my $sub (@subs) {
    $sub->(@args[ signature($sub)->positions ]); # for utility?
}

  Yeah, that one would also need to be far more complex.  Not gonna fly.
 

for my $sub (@subs) {
    signature($sub)->laxcall($sub, @args); # for even more utility?
}

  That one could still work. :)


Eirik

Reini Urban

unread,
Oct 28, 2012, 3:09:57 PM10/28/12
to perl5-...@perl.org
So please explain to me the case in which the compiler cannot see too
many arguments, and this decision has to be postponed to run-time.

sub test ($x, @foo, @bar) {} must be a compile-time error.
There can only be one slurpy (arrays or hashes) argument in
declarations, and it must be the last.

sub test ($x, @foo) {}
test() must be a compile-time error.

sub test ($x, @foo) {}
test(1); test(1, 2); test(1, 2, 3);
cannot not be a compile error, and it cannot be a run-time error.
@foo can be empty.

What run-time errors are you talking about?

Peter Martini

unread,
Oct 28, 2012, 3:16:57 PM10/28/12
to Reini Urban, perl5-...@perl.org
Speaking of the run-time problem in general:

sub twox($i){ say $i * 2;}
sub threex($i){ say $i * 3;}

my @subs = qw(twox threex);

&$_(5) for @subs;

Lukas Mai

unread,
Oct 28, 2012, 3:26:47 PM10/28/12
to perl5-...@perl.org
On 28.10.2012 20:09, Reini Urban wrote:
> On 10/25/2012 12:09 PM, Aristotle Pagaltzis wrote:
>> TL;DR: Some arity mismatch errors *can* be detected at compile time, and
>> those *should* be – eventually, it doesn’t have to be part of the
>> first iteration. Other arity mismatch errors *cannot* be detected
>> at compile time, and those necessarily will be runtime errors.
>>
>> So this whole sub-thread is an unnecessary diversion.
[snip]

>> * Reini Urban <rur...@x-ray.at> [2012-10-25 17:25]:
>>> Of course @ and % ending parameters cannot be checked at all.
>>
>> This has nothing to do with trailing slurpy parameters. It has to do
>> with the fact that lists automatically flatten in Perl 5. `foo(@bar)`
>> will not call `foo` with a single argument, it will call it with any
>> number of arguments from zero to arbitrarily many.
>>
>> If `foo` expects three scalar arguments and `@bar` is a three-element
>> array, then there is absolutely no reason for this to be an error at
>> runtime, much less a parse error. It is well possible that the code
>> which calls `foo` is constructing the argument list dynamically but
>> makes sure to always put the right number of arguments in it. The parser
>> has no business trying to decide whether the program is wrong in that
>> case.
[snip]

> So please explain to me the case in which the compiler cannot see too
> many arguments, and this decision has to be postponed to run-time.

sub test($x, $y) {}

my @bar = (1) x rand 3;
test @bar;

my $ref = \&test;
...
$ref->(1, 2, 3);

> sub test ($x, @foo, @bar) {} must be a compile-time error.
> There can only be one slurpy (arrays or hashes) argument in
> declarations, and it must be the last.
>
> sub test ($x, @foo) {}
> test() must be a compile-time error.
>
> sub test ($x, @foo) {}
> test(1); test(1, 2); test(1, 2, 3);
> cannot not be a compile error, and it cannot be a run-time error.
> @foo can be empty.
>
> What run-time errors are you talking about?

See above.

Lukas

Aristotle Pagaltzis

unread,
Oct 28, 2012, 7:53:16 PM10/28/12
to perl5-...@perl.org
* Reini Urban <rur...@x-ray.at> [2012-10-28 20:15]:
> So please explain to me the case in which the compiler cannot see too
> many arguments, and this decision has to be postponed to run-time.
>
> sub test ($x, @foo, @bar) {} must be a compile-time error.
> There can only be one slurpy (arrays or hashes) argument in
> declarations, and it must be the last.

Yes.

> sub test ($x, @foo) {}
> test() must be a compile-time error.

Yes.

> sub test ($x, @foo) {}
> test(1); test(1, 2); test(1, 2, 3);
> cannot not be a compile error, and it cannot be a run-time error.
> @foo can be empty.

Yes.

> What run-time errors are you talking about?

Passing a list to a sub with no slurpy parameter.

sub test ($x, $y) {}
my @args = (1) x (rand * 4);
test @args;

Once in every 4 times this code will work, the other 3 it will bomb.
The compiler cannot decide whether it will or not.

demerphq

unread,
Oct 29, 2012, 3:10:25 AM10/29/12
to perl5-...@perl.org
On 29 October 2012 00:53, Aristotle Pagaltzis <paga...@gmx.de> wrote:
> * Reini Urban <rur...@x-ray.at> [2012-10-28 20:15]:
>> What run-time errors are you talking about?
>
> Passing a list to a sub with no slurpy parameter.
>
> sub test ($x, $y) {}
> my @args = (1) x (rand * 4);
> test @args;
>
> Once in every 4 times this code will work, the other 3 it will bomb.
> The compiler cannot decide whether it will or not.

And this is documented to be legal syntax and breaking it would break a LOT.

Aristotle Pagaltzis

unread,
Oct 29, 2012, 10:49:45 AM10/29/12
to perl5-...@perl.org
* demerphq <deme...@gmail.com> [2012-10-29 08:15]:
> On 29 October 2012 00:53, Aristotle Pagaltzis <paga...@gmx.de> wrote:
> > * Reini Urban <rur...@x-ray.at> [2012-10-28 20:15]:
> >> What run-time errors are you talking about?
> >
> > Passing a list to a sub with no slurpy parameter.
> >
> > sub test ($x, $y) {}
> > my @args = (1) x (rand * 4);
> > test @args;
> >
> > Once in every 4 times this code will work, the other 3 it will bomb.
> > The compiler cannot decide whether it will or not.
>
> And this is documented to be legal syntax and breaking it would break
> a LOT.

I’m curious how much it really would break.

It will only affect newly written subs after all. The only backcompat
concern I can think of is in cases where a user may pass a reference so
a signature-bearing sub to existing code that calls passed-in subs with
a pile of arguments without caring how many of those arguments the
recipient wants.

But even that case it can be worked around, e.g. by passing a wrapper
anonsub with a slurpy parameter that then plucks the right number of
arguments out of that array and then calls the wrapped signature-bearing
sub with it.

So I don’t see this breaking appreciable amounts of old *code*.

It may break old *habits*. Even so, it seem like little burden to use
one of the several ways to step around the issue when that is in fact
called for.

So I’m not worried.

Regards,

Ruslan Zakirov

unread,
Oct 29, 2012, 9:58:00 PM10/29/12
to Peter Martini, Perl 5 Porters
Hi,

Here is summary of the thread.

This thread was about "too many arguments" in call to a sub with a
signature, for example:

sub foo($a, $b) {...};
foo(1,2,3);

This was not about "not enough arguments". This was not about "signatures with
slurpy args". There was no person to insist hard on "No die! No warn!
The only way
it should be is to silently ignore". See "other comments" at the end
for comments
on these additional topics that still were touched in the thread.

Mainly choice was between die and warn.

1) die

If such call dies then there is no way for caller to say "I know
what I'm doing, just ignore arguments you don't need". Yves brought the
following example:

for my $sub (@subs) {
$sub->(@args);
}

A few proposed solutions to the problem:

a) By The Sidhekin:

for my $sub (@subs) {
no strict 'arity';
$sub->(@args);
}

And got +1 from Peter Martini.

There was debate on whether this stricture is enabled by default
or not, how it behaves in an old code calling a sub with signatures,
how it behaves with 'no strict'. Alternative pragmas were suggested,
but still idea is the same.

This is so far *the best candidate*, but pragma name and behaviour needs
research and discussion. Hopefuly somebody collects a summary on this
and initiates a targeted discusion.

Here you can stop reading this summary, jump to "other comments"
or continue to get more alternatives.

b) By Aristotle:

&foo(1,2,3)

It avoids prototypes already and may avoid signatures. Note that
`$sub->(@args)` and `&$sub(@args)` are indistinguishable right
now. He propose that the parser remember this difference so that
the former throws error. Yves liked idea.

c) By Eirik Berg Hanssen:

Instrospection, for example:

signature($sub)->laxcall($sub, @args);

It was agreed that introspection would be needed at some point, but
for the subject it's too big yak to shave.

d) ...

Sure callee (sub author) can be generous and put slurpy array at the end
that he really doesn't need and turn die into warn or silently ignore:

sub foo($bar, $baz, @ignored) {}
sub foo($bar, $baz, @excess) { warn "..." if @excess }

It was even suggested allowing nameless @ in signatures (by Aaron Crane).

However, people agreed that it's possible, but for sure is not right thing
to do for callee to help caller solve his problems.

2) warn

This was not discussed that much as the following by Aaron is good summary:

"My instinctive response is to prefer option "die". I do take your point
about option "warn" moving the control from the callee to the caller; that
does sound tempting. But I think I'm essentially always going to want
an exception for excess arguments, so having to say `use warnings
'all', FATAL => 'excess_arguments'` sounds like quite a lot of
boilerplate for what I'm expecting will be the common case in new,
careful code".

Other comments:

Note that @_ is not available in a sub with signatures, so "silently
ignore" means that you have no access to arguments that were not assigned
by the signature (H.Merijn Brand brought this up).

Jesse Luehrs brought up "not enough arguments, default values and friends".
From my point of view he had very good summary: "Maybe this just means that
strict-by-default is the right answer, and I can write old-style subs if I
need defaults until defaults are implemented?". I can only add "until
defaults and *optionals* are implemented". Aaron Crane agrees.

It was showed that in perl6 not enough and two many positional arguments
are fatal, but sub without an explicit signature is slurpy.

sub f($x,$y) {}
f 1; # not enough
f 1,2,3; # too many
# but
sub f {...}; f(1,2,3); # is ok


Reini Urban brought up compile time signature checks. People do agree
that it's good to get, but it's not possible to do all the time and
for the first iteration it's ok for it to be run time checks.

Also, people started flaming about "die is always run-time, compile-time
we call it croak." Noise in constructive discussion on the subject.
Stay on subject or start a new thread!!!

--
Best regards, Ruslan.

Dave Mitchell

unread,
Oct 30, 2012, 8:00:43 AM10/30/12
to Reini Urban, perl5-...@perl.org
On Sun, Oct 28, 2012 at 02:09:57PM -0500, Reini Urban wrote:
> So please explain to me the case in which the compiler cannot see
> too many arguments, and this decision has to be postponed to
> run-time.

sub f1($x) { ... }
sub f2($x,$y) { ... }

*f2 = \&f1 if rand > 0.5;
# or
$::{f2} = *f1 if rand > 0.5;

f2(1,2);


--
O Unicef Clearasil!
Gibberish and Drivel!
-- "Bored of the Rings"

Reini Urban

unread,
Nov 1, 2012, 2:38:43 PM11/1/12
to pp
On Tue, Oct 30, 2012 at 7:00 AM, Dave Mitchell <da...@iabyn.com> wrote:
> On Sun, Oct 28, 2012 at 02:09:57PM -0500, Reini Urban wrote:
>> So please explain to me the case in which the compiler cannot see
>> too many arguments, and this decision has to be postponed to
>> run-time.
>
> sub f1($x) { ... }
> sub f2($x,$y) { ... }
>
> *f2 = \&f1 if rand > 0.5;
> # or
> $::{f2} = *f1 if rand > 0.5;
>
> f2(1,2);

Good case.

But still:
With function reassignments or signature declaration changes or
prototype changes at run-time
it will also not make much sense to check signatures or arity at
run-time at all, because the
changed function also might have a changed signature.

I would let the user handle that cases and not check in entersub at
run-time if the signature belongs the
function and if the arguments match the signature. It will make
functions calls even slower.

Aristotle Pagaltzis

unread,
Nov 1, 2012, 5:59:18 PM11/1/12
to perl5-...@perl.org
Hi Reini,

* Reini Urban <rur...@x-ray.at> [2012-11-01 19:40]:
> On Tue, Oct 30, 2012 at 7:00 AM, Dave Mitchell <da...@iabyn.com> wrote:
> > sub f1($x) { ... }
> > sub f2($x,$y) { ... }
> >
> > *f2 = \&f1 if rand > 0.5;
> > # or
> > $::{f2} = *f1 if rand > 0.5;
> >
> > f2(1,2);
>
> Good case.
>
> But still:
> With function reassignments or signature declaration changes or
> prototype changes at run-time it will also not make much sense to
> check signatures or arity at run-time at all, because the changed
> function also might have a changed signature.

How can that even matter? The signature is tied to the CV being called,
not to the glob or some other separate data structure. The number of
arguments is therefore always accurate for the actual CV being called.

> I would let the user handle that cases and not check in entersub at
> run-time if the signature belongs the function and if the arguments
> match the signature. It will make functions calls even slower.

It’s a single integer comparison and the number of arguments passed is
available for free at call time already. So in theory the added cost on
the hot path in the common case should be 2–3 instructions, doing one
indirect memory access to load number of expected arguments from CV, and
with good prediction hit rate for the branch. Not free but seems like it
should be about as cheap as a feature can possibly be.

And @_ is already not being set up, so these calls are way faster than
normal in the first place so a tiny addition in overhead will be offset
by a large subtraction.

Of course this is all hypothetical and will have to pass the crucible of
practice, but I see no reason to not even try it.
0 new messages