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
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