New release of Method::Signatures is on its way to CPAN. I'm in a sprint to get all the sizzle implemented before PPW.
This release features improved parsing of method attributes, thanks to stealing code from Florian Ragwitz's MooseX::Method::Signatures.
Some parameter traits have been implemented. "is alias" lets you work with the parameter as an alias, altering it in the caller's namespace. Previously this was only possible by manipulating @_ directly.
These two are equivalent.
sub strip_ws {
my $self = shift;
$_[0] =~ s/^\s+//;
$_[0] =~ s/\s+$//;
return;
}
method strip_ws($str is alias) {
$str =~ s/^\s+//;
$str =~ s/\s+$//;
return;
}
my $str = " support the right to arm bears ";
Class->strip_ws($str); # works in place on $str
During the initial arguments about how signatures should work on p5p one of the longest and loudest arguments was whether or not they should copy or alias by default. Perl 6 aliases, but Perl 6 is an "everything is an object" language which passes by reference all over the place. Perl 5 is not. Like it or not, Perl 5 copies. So copying is the default. But every once in a while you want aliasing, so here it is.
"is ro" makes a parameter read only (using the Readonly module). Now you can apply some strictness to your subroutines.
method echo($msg is ro) {
return $msg;
}
If echo() tried to alter $msg it would throw an error.
Required and optional parameters are finally implemented. All positional parameters are required by default. Parameters with defaults are optional.
# $x and $y are required. $z is optional and defaults to 0
method print_position($x, $y, $z=0) {
print "$x, $y, $z";
}
# $url is required. $user and $pass are optional.
method get($url, $user?, $pass?) {
...
}
The code generated for the required argument check is redundant (use B::Deparse to see it) and could be tightened up to improve performance. If someone wants to try out some relatively low hanging fruit, that's it. It's on Github so feel free to make a fork and work on it.
Next version will implement named parameters. After talking it over with Florian I think I'm going to go with his semantics from MooseX::Method::Signatures. Named parameters are declared with
# year is required. The rest are optional and have defaults.
# They are all readonly.
method date2epoch(:$year! is ro,:$month = 1 is ro, :$day = 1 is ro,
:$hour = 0 is ro, :$min = 0 is ro, :$sec = 0 is ro) {
...
}
# Jan 1st, 2008 00:00:00
my $epoch = Date->date2epoch( year => 2008 );
# One minute after midnight
my $epoch = Date->date2epoch( year => 2008, min => 1 );
# $text is positional, the rest are named and optional
method format($text,:$justify = "left", :$quality) {
...
}
# left justified
Class->format("mu");
# right justified, Livejournal quality poetry.
Class->format(<<'POETRY', justify => "right", quality => "LJ");
...
POETRY
Just how much code does this save? Here's date2epoch() written out long-hand.
sub date2epoch {
my $self = shift;
my %args = @_;
croak "date2epoch() missing required argument \$year"
unless exists $args{year};
Readonly my $year = $args{year};
Readonly my $month = $args{month} || 1;
Readonly my $day = $args{day} || 1;
Readonly my $hour = $args{hour} || 0;
Readonly my $min = $args{min} || 0;
Readonly my $sec = $args{sec} || 0;
...
}
Wow, even I'm surprised! Do you really need all that? No, you could do without Readony and you could leave everything in %args. But with Method::Signatures you no longer need to compromise with verbosity. You can have all the features and compact code.
Looks good! (Score:1)