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

Re: PSC #049 2022-01-07

Thread Previous | Thread Next
Paul LeoNerd Evans
January 10, 2022 18:36
Re: PSC #049 2022-01-07
Message ID:
On Mon, Jan 10, 2022 at 03:44:52AM -0800, Darren Duncan wrote:
> I vote for something like number 3.
> When a file says "use v5.36" or a higher version, it causes signatures to be
> available non-experimentally AND it causes @_ to not be declared within the
> scope of any sub using a signature, wherein any references to @_ will fail

@_ isn't "declared". It never has been, never would be.

After a dollar, at-sign or percent-sign, any single printing character
is permitted. If that printing char was a valid "start-of-identifier"
character, the parser then reads more chars to find a full identifier.
If not, then it stands for some superglobal punctuation var that is
always available - for instance, $!, $), etc...

Thus, by necessity, @_ always exists because _ is a printing character.

Making such code as

  my $x = shift @_;

fail to parse at parse time requires adding a bunch of special-case code
to the parser/compiler, to recognise that @_ must not be permitted
inside signatured subs.

Also, breaking the surface-syntax part of @_ is insufficient here,
because of all the implicit uses of the array inside `@_`. For example

  my $x = shift;

The parser never encounters the global *_ symbol here, nor the global @_
array. This gets compiled into an OP_SHIFT with a special flag which
tells the runtime to read GvAV(PL_defgv) to find the arguments array.

Forbidding this as well requires much more logic adding to the parser.

Now, all of theabove can be added - it's just a matter of writing more
code. Lots more code. In the parser. In lots of situations. It's a whole
bunch of work but a suitably-motivated individual could track down all
the cases and add them. Such a parser would be slower than it currently
is, because it has to check more things, but perhaps it wouldn't be
*much* slower that anyone could really measure. If it was, say, under 1%
slower on average, we're likely to be happy with the hit (because, on
average, computers get 1% faster every few weeks anyway so overall the
situation is already better than the last time we looked at it).

But now consider some purely-dynamic runtime things that the parser
could not know about:

  no strict 'refs';
  my $sym = "some code here";
  my $val = shift @{$sym};

The parser can't possibly know that $sym might be given as "_" and thus
we'll have to defer this to runtime. Rik already points out in another
mail, why that is hard and requires adding magic to the GvAV(PL_defgv)
AV which would therefore slow down *all functions* in *all perl
programs*, regardless of whether that function happened to use
signatures, or even if any function at all in the program ever does.


> This stricter behaviour should not break any existing code because it only
> occurs when they explicitly "use v5.36" or they otherwise use-signatures
> without experimental, meaning it is a change they explicitly opted into in
> the same file as the affected sub.

Not directly related to your comment, but while we're here: There is
already much code on CPAN and elsewhere (and I know because I have
written some of it) that still makes use of @_ within a signatured sub.
There's two usecases:

  1: Forwarding all the arguments to a wrapper function

       sub wrap ($x, @) {
         warn "called wrap with x=$x";
         otherfunc(@_);   # just makes this easier

  2: Determining the argument-count, in order to distinguish passing an
     `undef` from not having an argument at all:

       sub field ($self, $new=undef) {
         if(@_ > 1) {
           $self->{field} = $new;
         return $self->{field};

       print "field is ", $obj->field;

     Yes I know this code is hideous and personally I hate that style
     but it remains synatically- and semantically-valid perl that
     nevertheless many folks actually do write, and want to continue to

Quite aside from any "it might perform faster" or "it helps users avoid
bugs" arguments that might be put forward in favour of banning the use
of @_ in signatured subs, we need to keep these two usecases in mind
(among possibly others), and ensure we continue to provide for them.

It would be a shame if we had to tell users they can't perform behaviour
like either of these two cases, if they wish to use signatured subs.


Paul "LeoNerd" Evans      |  |

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