-
-
Notifications
You must be signed in to change notification settings - Fork 17
Type system
See the perltypes documentation from master,
and the latest version is usually in the feature/gh7-signatures
or featurex/gh16-multi
branch.
In the featurex/gh7-sigs+libs branch several libraries are already "modernized", i.e. converted to typed signatures.
See for example the modernization of Test-Simple in commit 2d39610cb5.
The translation is pretty straightforward:
-sub is_eq {
- my( $self, $got, $expect, $name ) = @_;
+sub is_eq ( $self, $got?, $expect?, $name?) {
The ?
suffix from perl6 denotes an optional argument. If left out in the call, the value will be undef. There's no arity inspection as in @_
.
$self
is still in the signature. When is_eq
is declared as method and not as sub, $self is not needed anymore and should be omitted. This is currently in work in the feature/gh16-multi
branch.
-sub skip {
- my( $self, $why, $name ) = @_;
- $why ||= '';
- $name = '' unless defined $name;
+sub skip ( $self, str $why='', $name? ) {
$self->_unoverload_str( \$why );
$why
is declared with the str
coretype. str
is the unboxed variant of the perl5-level boxed Str
type, same as in Perl6. That means the compiler accepts only strings, not other scalars, and only strings which are known to the compiler at compile-time. Those strings will then be optimized to fast unboxed variants if possible or not, as the compiler sees fit.
A call to skip needs to stringify the $why argument, otherwise you get a compile-time error.
skip($test->{why}, "not working yet"); will be invalid.
skip("$test->{why}", "not working yet"); is invalid.
$name?
should have also been declared as str $name=undef
instead. This is currently valid code I think, but inconsistent with the current type system. undef is no str type.
It really should be str? $name?
, str?
denoting str or the Undef type.
The type int
cannot overflow to a float, a number. This is just as under use integer
. Arithmetic ops with int
are much faster than with generic numbers of type Numeric. E.g. the generic add
op is 50 lines of c code, which calculates the sum twice and checks both args for UV, IV or NV, and the for possible overflow. The optimized Int
variant for add where both arguments are int is one line, and 10x faster.
The optimized int variant where both arguments are unboxed, true native ints, is 20x faster, as the value needs not be extracted from the SV head, the result needs not be changed to an SvIV, it is just a single word.
But with the declared int type you cannot just pass normal expressions to this method anymore. E.g. with the skip similar to above, just as Test::More function and declared as
cpan/Test-Simple/lib/Test/More.pm
-sub skip {
- my( $why, $how_many ) = @_;
+sub skip ( str $why, Int $how_many = 0) {
my $tb = Test::More->builder;
- unless( defined $how_many ) {
+ unless ($how_many) {
We need the numeric argument $how_many
, which is often mixed up with str $why
.
We can declare $how_many as int, Int or Numeric, but overflow to NV (the Num type as in perl6) makes no sense as $how_many is later used as loop counter.
So we have to fix several wrong type usages of this skip, as seen below.
-- cpan/Test-Harness/t/source_handler.t
+++ cpan/Test-Harness/t/source_handler.t
@@ -355,9 +355,9 @@ sub test_handler {
SKIP:
{
- my $planned = 1;
+ my int $planned = 1;
$planned += 1 + scalar @{ $test->{output} } if $test->{output};
- skip $test->{skip_reason}, $planned if $test->{skip};
+ skip "$test->{skip_reason}", $planned if $test->{skip};
We need to stringify the $why argument, and type the $planned number to int to bypass the type checker.