Embed presentation
Download to read offline
Sub Signatures Next Steps Peter Martini github.com/PeterMartini PeterCMartini@GMail.com @PeterCMartini
We did it!
use feature 'signatures' now available in 5.20 Thanks @rjbs and Zefram
1) Review last year's talk 2) What's in 5.20 3) What's contentious in 5.20 4) Potential enhancements for 5.22 5) Long term enhancements
Goals from last year's talk: Add API for get/fetch – X Add API for parsing – X Add a new module – ✓ Update CPAN signatures – X Performance boost – X
What's in 5.20?
All of the following assumes: use feature 'signatures'; no warnings 'experimental';
Named Parameters sub foo($bar, $baz)
Anonymous Parameters sub foo(,ドル $baz)
Default Values my $n = 1; sub update($rec, $id = $n++)
Default Values (but only for scalars) sub nope(@arr = (1,2)); # syntax error
Strict Checking sub twoargs($one, $two) {} twoargs(1); # dies
Strict Checking sub usedef($one, $two=2) {} usedef(1); # lives!
With Attributes: sub foo :prototype($) ($bar) {}
How it works:
Perl, while parsing, rewrites signatures into equivalent opcodes
perl -MO=Deparse -Mfeature=signatures -e 'sub foo($bar){}' The signatures feature is experimental at -e line 1. sub foo { use feature 'signatures'; die 'Too many arguments for subroutine' unless @_ <= 1; die 'Too few arguments for subroutine' unless @_ >= 1; my $bar = $_[0]; (); }
After parsing, there is no trace left of what the signature was
What's contentious in 5.20?
In 5.18 and before: sub CONSTANT(){ 5 } Replaced by a constant at runtime
In 5.20, it becomes: sub CONSTANT { use feature 'signatures'; die 'Too many arguments for subroutine' unless @_ <= 0; (); 5; }
sub foo : lvalue ($bar) {} # Legal sub foo : lvalue($bar) {} # Syntax error
sub foo($bar); # Syntax error
No path to making use feature 'signatures'; a default
This is why it's still experimental
Goals for 5.22:
Get past experimental!
Revisit signature placement
Right now we have: sub <name> <proto> <attr> And: sub <name> <attr> <sig>
Having the signature after the attributes can cause subtle bugs
Having the signature after the attributes makes coexistence of prototypes and signatures much harder
Especially problematic for sub CONSTANT() {}
Make signatures faster
signatures right now do no more than rewrite your code
Which means it is exactly as fast as doing it by hand
This does not have to be the case
Preserve the signature
Not just for aesthetics; preserving the signature allows sub CONSTANT(){} to work again
Among other optimizations
Tweak error handling
signatures right now injects a 'die' into the sub if the arguments don't match
Which means the error is reported in the sub, not the caller
This is fixable for 5.22
Possible enhancements for 5.22
A separate feature to have signatures imply prototypes
Having a compatibility mode for signatures would allow safely* turning it on by default
safely* - code that warned about illegal prototypes would now probably die; CPAN modules that hijack prototypes would have to be modified to turn off signatures
Allow signatures in sub declarations
Aside: signatures v. initialization block
Defaults in declarations is a sticky subject
# This is bad our $bar; sub foo($baz = $bar); ... { my $bar = 5; sub foo($baz = $bar) {} }
# This isn't any better! sub foo($baz); ... { my $bar = 5; sub foo($baz = $bar) {} }
# This one's sticky ... sub foo($); ... { my $bar = 5; sub foo($baz = $bar) {} }
# Maybe this? sub foo($baz = ...); ... { my $bar = 5; sub foo($baz = $bar) {} }
Fatalize redefinition
Not necessary, but enables optimizations
(sub redefinition already breaks prototypes)
Long term enhancements
Particularly things that can benefit from core
Readonly args sub foo($bar : ro)
Native types sub foo(int $a, num $b, str $c)
Package types sub foo(Some::Class $bar)
Calling parameters by name
sub foo (-bar, -baz = 2) {} foo(-bar => 1); This could be made as fast as simple assignment
Aliasing
sub foo($bar : alias) { $bar = "New"; } my $var = "Old"; foo($var); # $var is now "New"
Implicit $self (method keyword? There's a method attribute already)
Custom handler for sub redefinition
Which would allow multi methods on CPAN
Retrieve signature as a core function
API to override signature parsing
The goal is to let you make promises to Perl, which Perl can enforce for your sanity and its speed
Questions?
Thank you for coming