develooper Front page | perl.perl5.porters | Postings from November 2019

@_ Suppression

From:
Dave Mitchell
Date:
November 28, 2019 17:03
Subject:
@_ Suppression
Message ID:
20191128170316.GD3573@iabyn.com
=head2 Synopsis:

    @_ will not be set, unset or localised on entry to or exit from
    a signatured sub; it will still be the @_ of the caller. But any use
    of @_ within the lexical scope of sub a sub will warn.

At the moment we still populate @_ on signature sub calls, which entails
considerable overhead. There have been some discussions about when @_
should be populated, and if it isn't, what value (if any) it should have.
See:

    http://nntp.perl.org/group/perl.perl5.porters/233053

I propose the following:

1) @_ is *always* untouched by the call to the signature function; it is
still the same AV as the caller's: it's as if the call had been made using
the '&foo;' argless call mechanism, and any attempt to modify @_ actually
modifies the parent's @_ (or grandparent's or whatever, depending on
whether the parent etc subs also have a signature).

2) There will be *no* facility (via a pragma or otherwise) to re-enable
@_-populating. I think this is probably the most controversial part of
this proposal, but after a lot of thought I feel strongly about this. It
has the huge advantage of not needing twin code paths to support both
types of argument access, and the need for twice as many tests.  It also
side-steps ambiguities: for example, what happens if a parameter's default
expression modifies @_? Is that seen by subsequent parameters?

The main argument I recall being made for retaining both forms is for when
converting existing code to use signatures, where some of that code may
still use @_ directly or indirectly, e.g.

    sub foo { 
        my (...) = @_;  # easy to spot and convert
        ...
        bar(@_);        # might be missed
    }

However, I think (or at least hope) that any use cases of that sort will
be satisfied by my next two points.

3) I propose that within the direct lexical scope of a signature sub, any
code which uses the @_ variable (both rvalue and lvalue use, and as a
container or as individual elements),  where detectable by the parser,
will trigger a compile-time warning. This should catch most of the
code-conversion issues mentioned above. For the occasional case where you
really do need to use @_ (such as tail-call elimination), just turn off
the warning:

    sub foo (...) {
        ...
        no warnings 'signature';
        local @_ = (1,2,3); # 'local' because we're modifying the *parent* @_
        goto &bar;
    }

Such warnings will extend to any use of @_ within evals etc that are
themselves within the lexical scope of the sub, but they don't extend to
other subs within the lexical scope; for example, this won't warn:

    sub foo (...) {
        my $s = sub { my ($x,$y) = @_; .... }
    }

I'm sure there will be ways to bypass the 'use of @_' warning by directly
manipulating stashes and globs, but perl has always allowed you the rope
to hang yourself if you so desire.

4) With my 'Query Parameters' proposal (see "Query Parameters" thread),
just about any need you may have had for @_ - such as determining whether
a parameter was bound to an argument or to a default expression - can now
be done (usually more easily) with query parameters (these 'query' the
remaining arguments by peeking ahead, but don't actually consume any of
them). As a trivial degenerate case, the equivalent of @_can be
reconstructed as a lexical variable by using an aliasing array query
parameter as the first element of a sub's signature:

    sub foo(?*@args, .....) { ... } # @args equivalent to @_

Note that you can't do

    sub foo(?*@_, .....) { ... }

as we don't allow @_ (nor $_ nor %_) as a lexical, nor as a parameter
variable name. I see no need to change that.

Similarly, boolean query parameters allow you to see whether an argument
was available for the next parameter:

    sub foo(??$saw_x, $x = 0) {{ ... }

The warnings category: I propose a new category called 'signature'
which includes the @_ warning plus any other new signature-related
warnings we might add. (At the moment there are no such warnings: all
current signature issues are croaks rather than warns.) But I'm open to
other suggestions - perhaps one of the existing categories is suitable?



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