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

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

Thread Previous | Thread Next
From:
Alexander Hartmaier
Date:
January 19, 2022 20:43
Subject:
Re: Things you can't do in a signatured sub
Message ID:
CAB49Qra5KrswEBvBsmiG1WTE7maSm-pcHVKuVOCPBJ58WSO-Pw@mail.gmail.com
On Wed, Jan 19, 2022 at 7:00 PM Paul "LeoNerd" Evans <leonerd@leonerd.org.uk>
wrote:

> I'm currently having a bit of hack at the docs in perlsub.pod,
> adjusting the wording about @_ when talking about signatured
> subroutines (ahead of merging my branch[1] to add discouragement
> warnings to it). I feel it would be useful to keep in mind a concrete
> list of the things that signatured subs don't let us do right now, so
> we can think about future ideas:
>
>   * Setting @_ so you can do a 'goto &SUB' tailcall (or a perl4-style
>     call but we don't like those any more); much as you would with
>
>       sub not_signatured {
>         @_ = ("args", "to", "callee");
>         goto &elsewhere;
>       }
>
>       sub signatured($x) {
>         @_ = ...  # not allowed
>       }
>
>   * Seeing the entire collection of arguments so you can write a simple
>     wrapper-function and forward on everything to a callee:
>
>       sub not_signatured {
>         my ($x) = @_;
>         warn "Calling with x=$x\n";
>         return otherfunc(@_);
>       }
>
>       sub signatured($x, @) {
>         warn "Calling with x=$x\n";
>         return otherfunc(@_);  # not allowed
>       }
>
>   * As a variant of the above; you can't even see the count of passed
>     arguments in order to distinguish no-argument from being explicitly
>     passed undef (or whatever the param default is)
>
>       sub not_signatured {
>         my ($x) = @_;
>         warn "X was " ? (@_ ? "the value $x" : "not passed");
>       }
>
>       sub signatured($x = undef) {
>         # impossible to distinguish signatured() from signatured(undef)
>       }
>
>   * Assigning to or otherwise mutating the caller's arguments:
>
>       sub not_signatured {
>         $_[0] = uc $_[0];
>       }
>
>       sub signatured($x) {
>         $_[0] = uc $x;  # not allowed
>       }
>
> If we make signatures non-experimental and add the warning about @_
> being forbidden, we should keep these cases in mind. At the very least
> I'd like to document them, but ideally we should further investigate,
> for each of them, whether we're actually happy to tell users "yeah,
> don't do that" or whether we feel we need to provide some alternative
> facility to allow them to continue writing functions to perform that
> kind of behaviour, while using signatures.
>
>
> [1] - https://github.com/Perl/perl5/pull/19346
>
> --
> Paul "LeoNerd" Evans
>
> leonerd@leonerd.org.uk      |  https://metacpan.org/author/PEVANS
> http://www.leonerd.org.uk/  |  https://www.tindie.com/stores/leonerd/
>

I have one sad example to add: defining a sub that is passed as a callback
to a module which doesn't document the (number of) arguments and call it in
different parts with a different number of arguments. Example I'm just
dealing with is Mojo::RabbitMQ::Client.
In the end I gave up and didn't specify a signature to avoid exceptions
caused by the different number of arguments.

One more I can think of is different sub behavior depending on the number
of arguments, like multi-dispatch but inside the sub.
Then naming the arguments might be hard because for example the first one
holds something different when paired with a second arg.

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About