Mailing List Archive

RE: [EXTERNAL] getting signatures out of experimental
Every now and then, such as when a thread like this one comes along and I happen to notice, I re-read perldoc perlsub, and conclude that there is still no way to write a function with a prototype that is universally understood within, and outside, the scope of use feature ‘signatures’, including in older versions of perl. As long as signatures seemed perpetually experimental, I ignored the issue. Now it seems like time to speak up.

No doubt everyone close to the issue is familiar with the following paragraphs from perldoc perlsub:

There is a potential syntactic ambiguity between signatures and prototypes (see "Prototypes"), because both start with an opening parenthesis and both can appear in some of the same places, such as just after the name in a subroutine declaration. For historical reasons, when signatures are not enabled, any opening parenthesis in such a context will trigger very forgiving prototype parsing. Most signatures will be interpreted as prototypes in those circumstances, but won't be valid prototypes. (A valid prototype cannot contain any alphabetic character.) This will lead to somewhat confusing error messages.

To avoid ambiguity, when signatures are enabled the special syntax for prototypes is disabled. There is no attempt to guess whether a parenthesised group was intended to be a prototype or a signature. To give a subroutine a prototype under these circumstances, use a prototype attribute.

… and likely, the issue has been debated to death, in places not found by my admittedly cursory searches. So, my $0.02 are likely redundant and non-original, but the gist is that if signatures become non-experimental, I will not relish having to start maintaining two versions of modules that have until now been compatible with any and every release of perl5. I will most likely give up support for the oldest versions of perl – but first would need to know when :prototype() syntax was added (Aside: I haven’t yet taken the time to rummage through every perldelta page – is there a place to see them all as one document, so I can search?)

The aforementioned two cents:


* suppose that we did try to guess, considering a parenthesized group to be a prototype if it contains non alphanumerics. Has it been decided that “somewhat confusing error messages” (presumably, when feeding new, signature-using code to older perls) outweighs not being able to write completely version-agnostic code?
* why not have a perl release (or three) with less-forgiving prototype parsing and less-confusing error messages, before finally enabling the eagerly-awaited signatures?

Apologies for my naivete/beating a dead horse/having missed memos/coming late to the party/having not dug deeply enough to answer the above for myself.

In hopes of adding something along the lines of what’s being asked about: strongly warning on use of @_ in the presence of a signature seems a fine improvement, but I fear that uproar over breakage of classic-prototype-using code when signatures become non-experimental (maybe not in CPAN, but in less-public code) will be the dominant effect. Point being, if there’s any further tweaking to be done before enabling signatures widely – maybe it should be focused on easing transition from the old.

stephan();

From: Ricardo Signes <perl.p5p@rjbs.manxome.org>
Sent: Sunday, November 21, 2021 1:13 PM
To: Perl 5 Porters <perl5-porters@perl.org>
Subject: [EXTERNAL] getting signatures out of experimental

Porters,

We introduced experimental signatures to the language over six years ago, and they are still experimental, and everybody knows that I would very much like to end this experiment so that we can use signatures in our code without fear of their breakage. Recently, I've had some conversations with people about whether we can "just remove the experimental flag." We haven't done so, over the years, because of discussion about making one kind of improvement or another. Has this been "the perfect is the enemy of the good enough?" I think to some extent it has, and now the question is "how much good within easy reach is good enough?"

That is: it would be very easy to just remove the flag, and that would be good. But if it's in our power to make one more really improving change that would have a significant cost later, maybe we should do just that. But we can't kick the can down the road indefinitely.

I have discussed this proposal a little bit with some people, but I am presenting it as my proposal and not any sort of dictate from the PSC. Here goes:

I propose that as soon as possible, we update signatured subroutines so that…

1. when a subroutine has a signature, the @_ variable is not populated when the subroutine is entered
2. when a subroutine has not set up @_ on entry, accessing @_ is a severe runtime warning, reading something like "Accessing @_ in a subroutine that has a signature is meaningless". (This could be caught sometimes at compile time, and it would be preferable, but not necessary, to do so when possible.)
We ship this in v5.36.0, with no further changes to signatures. (Any further improvements will come in future RFCs.) In v5.38.0, signatures are no longer experimental.

With that done, signatures are shipped and basically safe to use on code that uses them quite a ways back, as long as you're sure you didn't look at @_. Even if you require v5.38.0 in your code to avoid thinking about their behavior over the previous seven years, we'll have shipped stable signatures at long last.

What serious objects should prevent us from moving forward this way?

--
rjbs
Re: [EXTERNAL] getting signatures out of experimental [ In reply to ]
On Mon, Nov 22, 2021 at 12:18 AM Stephan Mueller via perl5-porters <
perl5-porters@perl.org> wrote:

> Every now and then, such as when a thread like this one comes along and I
> happen to notice, I re-read perldoc perlsub, and conclude that there is
> still no way to write a function with a *prototype* that is universally
> understood within, and outside, the scope of use feature ‘signatures’,
> including in older versions of perl. As long as signatures seemed
> perpetually experimental, I ignored the issue. Now it seems like time to
> speak up.
>
>
>
> No doubt everyone close to the issue is familiar with the following
> paragraphs from perldoc perlsub:
>
>
>
> There is a potential syntactic ambiguity between signatures and prototypes
> (see "Prototypes"), because both start with an opening parenthesis and both
> can appear in some of the same places, such as just after the name in a
> subroutine declaration. For historical reasons, when signatures are not
> enabled, any opening parenthesis in such a context will trigger very
> forgiving prototype parsing. Most signatures will be interpreted as
> prototypes in those circumstances, but won't be valid prototypes. (A valid
> prototype cannot contain any alphabetic character.) This will lead to
> somewhat confusing error messages.
>
>
>
> To avoid ambiguity, when signatures are enabled the special syntax for
> prototypes is disabled. There is no attempt to guess whether a
> parenthesised group was intended to be a prototype or a signature. To give
> a subroutine a prototype under these circumstances, use a prototype
> attribute.
>
>
>
> … and likely, the issue has been debated to death, in places not found by
> my admittedly cursory searches. So, my $0.02 are likely redundant and
> non-original, but the gist is that if signatures become non-experimental, I
> will not relish having to start maintaining two versions of modules that
> have until now been compatible with any and every release of perl5. I will
> most likely give up support for the oldest versions of perl – but first
> would need to know when :prototype() syntax was added (Aside: I haven’t yet
> taken the time to rummage through every perldelta page – is there a place
> to see them all as one document, so I can search?)
>
>
>
> The aforementioned two cents:
>
>
>
> - suppose that we *did *try to guess, considering a parenthesized
> group to be a prototype if it contains non alphanumerics. Has it been
> decided that “somewhat confusing error messages” (presumably, when feeding
> new, signature-using code to older perls) outweighs not being able to write
> completely version-agnostic code?
> - why not have a perl release (or three) with less-forgiving prototype
> parsing and less-confusing error messages, before finally enabling the
> eagerly-awaited signatures?
>
>
>
> Apologies for my naivete/beating a dead horse/having missed memos/coming
> late to the party/having not dug deeply enough to answer the above for
> myself.
>
>
>
> In hopes of adding something along the lines of what’s being asked about:
> strongly warning on use of @_ in the presence of a signature seems a fine
> improvement, but I fear that uproar over breakage of
> classic-prototype-using code when signatures become non-experimental (maybe
> not in CPAN, but in less-public code) will be the dominant effect. Point
> being, if there’s any further tweaking to be done before enabling
> signatures widely – maybe it should be focused on easing transition from
> the old.
>
>
>
> steph*a*n();
>

You don't have to write things to be compatible with both versions, because
signatures will always require opting in (partially because of this
ambiguity), and because :prototype is available in all perl versions that
contain the signatures feature.

-Dan
Re: [EXTERNAL] getting signatures out of experimental [ In reply to ]
On Mon, Nov 22, 2021 at 12:18 AM Stephan Mueller via perl5-porters <
perl5-porters@perl.org> wrote:

>
> - suppose that we *did *try to guess, considering a parenthesized
> group to be a prototype if it contains non alphanumerics. Has it been
> decided that “somewhat confusing error messages” (presumably, when feeding
> new, signature-using code to older perls) outweighs not being able to write
> completely version-agnostic code?
>
> Guessing is not possible, because some of the most common prototypes
(still) are completely valid signatures: (), ($), (@)

-Dan
RE: [EXTERNAL] getting signatures out of experimental [ In reply to ]
Thanks Dan, for setting me straight.

On Sunday, November 21, 2021 9:23 PM Dan Book grinnz@gmail.com<mailto:grinnz@gmail.com> wrote (in two messages that I’ve merged here):
" On Mon, Nov 22, 2021 at 12:18 AM Stephan Mueller via perl5-porters perl5-porters@perl.org<mailto:perl5-porters@perl.org> wrote:
" " ... I will most likely give up support for the oldest versions of perl -
" " but first would need to know when :prototype() syntax was added (Aside: I
" " haven't yet taken the time to rummage through every perldelta page - is
" " there a place to see them all as one document, so I can search?)
"
" You don't have to write things to be compatible with both versions,
" because signatures will always require opting in (partially because of
" this ambiguity), and because :prototype is available in all perl versions
" that contain the signatures feature.

D'oh! Of course, 'experimental' and 'enabled by default' are orthogonal.
Sorry for the noise.

" " - suppose that we did try to guess, considering a parenthesized group to
" " be a prototype if it contains non alphanumerics. Has it been decided
" " that "somewhat confusing error messages" (presumably, when feeding new,
" " signature-using code to older perls) outweighs not being able to write
" " completely version-agnostic code?
"
" Guessing is not possible, because some of the most common prototypes
" (still) are completely valid signatures: (), ($), (@)

Not knowing for sure is what makes it a guess :-) but I understand not
wanting to add any more heuristics to perl parsing.

I think that silently treating signatures as prototypes is a more
compelling reason for disabling old prototype syntax than confusing
errors. FWIW, an additional sentence at the end of the relevant paragraph
(A SUGGESTION IN CAPS) would likely have kept me from raising the idea
of guessing (presumably for the umpteenth time):

[...] Most
signatures will be interpreted as prototypes in those circumstances,
but won't be valid prototypes. (A valid prototype cannot contain any
alphabetic character.) This will lead to somewhat confusing error
messages. THOSE THAT ARE VALID -- FOR EXAMPLE (), ($) and (@) -- WILL
SILENTLY HAVE DIFFERENT MEANINGS THAN INTENDED.

stephan();