develooper Front page | perl.perl5.porters | Postings from December 2017

Re: Urgent subroutine signatures problems

Thread Previous | Thread Next
From:
Paul "LeoNerd" Evans
Date:
December 13, 2017 15:22
Subject:
Re: Urgent subroutine signatures problems
Message ID:
20171213152213.57f78ad6@shy.leonerd.org.uk
On Wed, 13 Dec 2017 15:46:59 +0200
Sawyer X <xsawyerx@gmail.com> wrote:

> I want to surface two critical subroutine signature issues, one
> previously raised by Zefram. These are urgent since they are breaking
> issues. We should discuss them and resolve them quickly.
> 
> It is better to break more things now than several times over time
> since each one resets the clock on the stability of signatures. We
> might as well resolve all breaking changes together.
> 
> 1. Lvalue subroutines are now broken as a result of the placement of
> subroutine signatures (RT #132141)[1]:
> 
> The reason for this is simple: Lvalue subroutines use the :lvalue
> subroutine attribute and subroutine attributes now come after the
> signature. Considering subroutine signatures can contain arbitrary
> code and :lvalue changes compilation, this, in effect, means that
> those features are now mutually exclusive. You cannot use :lvalue to
> affect compilation of any code in subroutine signatures.
> 
> One way to fix this would be to move subroutine signatures following
> subroutine attributes. Another fix would be to allow them both before
> *and* after, putting the responsibility on the user of using :lvalue
> (and such attributes that alter the subroutine in similar ways) before
> defining the subroutine signature. These solutions can be pretty
> fragile. Another option is to recognize which attributes should appear
> only before signatures and trigger an error if they appear after the
> signatures instead.

I haven't been keeping much eye on that part of the problem lately, but
as a quick thought: how easy is it to skip over the signature at a very
surface character-skipping level, find the attributes afterwards, apply
them, and then come back to properly parsing the signature? Is it as
easy as just counting the open and close parens, etc.?

I admit I have a slight personal oar in this one by way of (funnily
enough) Future::AsyncAwait, in which I'd find it useful to be able to
ask the parser to parse bits of signature for me, while I still
maintain overall control. There may exist scope for [pardon the pun] a
solution to both of these issues at once.

> 2. Having signatures available without explicitly enabling them
> 
> While we could "use feature" subroutine signatures, it would be even
> better if they were simply available without using a pragma. However,
> their syntax clashes with prototypes, meaning we can't have them
> enabled by default without breaking backward compatibility. We are
> forced to hide signatures behind a pragma.
> 
> Short-form prototype syntax is a stable feature that works by default
> on all versions since 5.002. The :prototype attribute didn't exist
> until 5.20, so backward-compatible code doesn't even have a choice
> about how to use prototypes. It would be wrong to break this.
> 
> If the syntax didn't clash, then we could have signatures enabled by
> default and not lose backward compatibility. Just as an example of a
> clear distinction between signatures and prototypes, Zefram suggested
> using square brackets for signatures[2]. This change would allow
> having subroutine signatures enabled without any pragma, which is
> quite appealing.

My view on this is that while I understand the motivation behind
"square signatures", I really don't feel the benefit of them is enough
to justify the cost in terms of the end result of the syntax.
Practically any other language which has an equivalent feature uses
parens here. Even ignoring other languages, there's a nice duality
currently between declaring the function and calling it, which we'd
lose with square signatures

  sub func($x, $y, $z) { ... }
  func("x", "y", "z");

Another way to look at this, is to consider the utility provided by the
'say' keyword. Useful as it is, it still has to be guarded by a
'use feature'. This eventually got feature-bundled into a version
declaration.

Can we not do the same for signatures? Since any code wishing to make
use of the signature syntax is going to break on any perl older than
5.20 (or is it 5.22? I have lost track), that code is going to have to
put

  use 5.020;

at the top. Can we just feature-bundle it into that? Probably best to
not retro-actively do it for 5.020 but start at 5.028 maybe? Anyone who
for some reason didn't want the feature can of course just

  use 5.028;
  no feature 'signatures';

if they wanted to stick to the old behaviour, but then at that point
they probably just want to fix their prototypes to use :prototype
instead.

-- 
Paul "LeoNerd" Evans

leonerd@leonerd.org.uk      |  https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/  |  https://www.tindie.com/stores/leonerd/

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