develooper Front page | perl.perl5.porters | Postings from January 2022

Re: Things you can't do in a signatured sub

Thread Previous | Thread Next
Darren Duncan
January 24, 2022 07:19
Re: Things you can't do in a signatured sub
Message ID:
On 2022-01-23 11:01 p.m., Ovid via perl5-porters wrote:
> On Monday, 24 January 2022, 07:50:33 CET, Darren Duncan <> wrote:
>> I still oppose as wrong-headed the concept of using such sentinel default values
>> to try and detect when no argument is passed.  The only use of such default
>> values is when you don't care to distinguish between users explicitly passing
>> that value from them not passing anything.  When you actually want to
>> distinguish them not passing a value, DON'T use defaults, and instead use "@" to
>> capture the list and test the list for presence of an element. -- Darren Duncan
> Then how do we fix the issue? What we *want* to know is how many arguments were passed to a variadic sub. You have this as an earlier example:
>      sub signatured(@maybe_x) {
>          if (scalar @maybe_x > 0) {
>              # we were given an argument, which may or may not be undef
>          }
>          else {
>              # we were not given an argument
>          }
>      }
> You've sort of turned @_ into @maybe_x and now you can pass 20 arguments to it, killing one of the strongest features of signatures. Both your example and @_ are to attempts to determine how many arguments were passed to a sub.

My example was the simplest version; in reality the "@foo" would only be used 
for the portion of the signature which is variadic, and any arguments that would 
always be passed are listed first as usual, eg:

     sub signatured($x, $y, @maybe_z) { ... }

Also I feel that when people are designing their subs properly, the number of 
optional parameters would be very few, usually zero, and otherwise the most 
common case would be exactly one parameter is optional, such as the combined 
getter/setter.  When you legitimately have a large number of optional arguments, 
that's when named arguments should be used.  Legitimately having more than 1 
optional positional argument only makes sense when each additional one is only 
used when all prior optional ones are also used.

Whenever parameter defaults are used, those defaults should always be a valid 
value of the parameter's data type, the same thing the user could have passed in 
explicitly but chose not to.  So typically that is zero if its a number, or 
false if its a boolean, and so on, not undef or some weird sentinel.

> Imagine if we had a $^NUM_ARGS variable (terrible name, though I think someone else suggested it):
>      sub name ( $self, $name=undef ) {
>          if ( $^NUM_ARGS == 2) {
>              $self->{name} = $name; # even if undef
>          }
>          else {
>              return $self->{name};
>          }
>      }
> By decoupling the signature from knowing how many args are passed, the solutions is much cleaner and we can't pass 20 arguments to the sub.

Now I actually like this proposal of yours a lot in principle.  Having another 
variable with the count that can be consulted.  And if we had that then it would 
be an elegant solution that means we can avoid the very problematic idea of 
sentinel values and not need slurpy "@foo" to deal with the variadic.

That being said, while it would mean a change to signatures, likely the best way 
to implement this is extend the signature syntax where one can declare a 
non-special lexical $foo to hold the argument count if they want it.

Here's an example I'm just making up:

     sub name ( $self, $name=undef, #$num_args ) { ... }

In that case, $num_args contains the count rather than declaring a parameter.

See also as I recall Raku supports special syntax for declaring the $self as 
well, like this:

     sub name ( $self: $name ) { ... }

So it would be a similar idea.

And we're not using up some special $^FOO when we don't really need to.

-- Darren Duncan

Thread Previous | Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About