Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: 05514649c3
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 279 lines (206 sloc) 9.446 kb

NAME

perltypes - Perl type system

DESCRIPTION

Dynamic types

Perl is a dynamic language with dynamic data types. The actual type is typically determined at run-time, context-dependent and usually the operator leads to automatic type conversions, cached in the data.

Types in lexical variables

Perl optionally allows storing the type, i.e. an existing package name, in the declaration of lexical variables. Lexicals are stored in pads, the package name, i.e. the type, is stored in the comppad_name slot for each pad. Up to version 5.18 Perl did not use these types for checks and optimizations, only external modules did.

Remember: A type is implemented as package. A valid type must be an existing and loaded package.

Global variables can not store types.

coretypes

With use coretypes Perl allows strict types of int, double and string, which can be applied to scalars, arrays and hashes. TODO: functions not yet. This would be the return type.

Any type change for those strictly typed variables will be detected at compile-time and if this fails at run-time. The type int is interpreted as IV, double as NV and string as PV only. There is no stringification for IV and NV, no magic such as "tie" in perlfunc, no setting to undef allowed.

const

"const" in perldata is a new type qualifier for lexical variables to enable compile-time readonly and assignment checks and type optimizations. You must assign a value within the declaration.

  my const $a = 0;
  my const($b,$c) = (0,1);
  my (const $d, $free) = (0,1);
  my (const int $i, const string $s) = (0,"1");

const sets the internal SVf_READONLY flag for the variable, if it's a scalar, array or hash. The special package stash (e.g. %MyClass::) counts as hash. Arrays and hashes are only shallow const, only the structure is protected, not the values. For deep constness you have to manually const all values also, or use a module.

Currently most const assignment violations are caught at compile-time, and if not you get at least an error at run-time.

Additionally to lexical variables we can also declare packages as const. That means that the structure of previously parsed package const stash can not me modified, shallow constness. You may not change, add or delete keys of the stash, but you may change the value of stash entries.

    const package MyBase { ... }
i.e.
    our const %MyBase:: = {}

Especially useful are declarations of const packages and the @ISA inheritance tree to optimize method calls at compile-time.

Compile-time type checks

Assignment to const variables are only allowed once during declaration with assignment.

    my const $i = 1;
    my const ($x,$y) = (0,1);
    my const @a = (0,1);
    my const %h = ('ok' => 1, 'nok' => 0);

Declaration of a const variable without initialization XXX 1. is a compile-time error (preferred) 2. is a compile-time warning 3. silently stores undef

As Perl itself supports no types, external modules such as coretypes, types, typesafety or MooseX::Types implement checks for their types during execution of "CHECK" in perlmod blocks, at quasi compile-time.

Compile-time type optimizations

Since Perl core does not deal with types stored in comppad_name per se, type checks and optimizations are deferred to the modules which implement respective types.

The only type optimization currently in effect is constant folding, and the change of compile-time static method calls, determined either by name or by type and const-ness of all searched packages to static function calls. Thus the dynamic method search, in which object this method is implemented is avoided. This is about ~10% faster.

Constant folding

Right-hand-side expressions which resolve at compile-time to constant integers may be optimized to a CONST value, and left-hand-side numeric ops may be optimized to use their optimized <i_> counterparts. Note that i_ ops do not overflow, the integer values just wrap around. So the type and data range must be determined in advance and if not possible i_opt promotion it is forbidden.

    my $c = $a + (1 << 8);
    => my $c = $a + 256;  # add $a CONST(IV 256)

    use coretypes;
    my int $a;
    my $c = $a + (1 << 8);
    => my $c = $a + 256;  # i_add $a CONST(IV 256)

    { use integer;
      my $a = 1;
      my $c = $a + (1 << 8);
    }
    => my $c = $a + 256;   # padsv($a) CONST(IV 1); i_add $a CONST(IV 256)

    { use integer;
      my $c = 1 + (1 << 8);
    }
    => my $c = 257;       # CONST(IV 257)

    my const $a = 1;
    my $c = $a + (1 << 8);
    => my $c = 257;       # CONST(IV 257)

Static method calls

    strict->import()
    => strict::import()

When the method is defined directly in the package, it is not possible to inject another package at run-time into the method search, thus the method call can be short-cut.

const packages

    const package MyBase 0.01 {
      our @ISA = ();
      sub new { bless { @_ }, shift }
    }
    const package MyChild 0.01 {
      our const @ISA = ('MyBase');
    }

    my $obj = MyChild->new;
    => MyClass::new()

When the method search goes only through const packages and their const @ISA, it is not possible to inject another package at run-time into the method search, thus the method call can be short-cut.

Note that the package MyBase must be constant here. Otherwise &MyBase::new can be deleted and @MyBase::ISA be changed to lead a parent object at run-time.

Types and const inheritance

    package MyBase 0.01 {
      our @ISA = ();
      sub new { bless { @_ }, shift }
    }
    package MyChild 0.01 {
      our @ISA = ('MyBase');
    }

    # closed call.
    my MyChild $obj = MyChild->new;
    => MyBase::new()

When the left-hand side of a method call is typed, the result of the method call must be of this type or any dependent type. $obj is already declared of type MyChild, thus it cannot be of any other run-time injected package.

    package MyBase 0.01 {
      our @ISA = ();
      sub new { bless { @_ }, shift }
    }
    const package MyChild 0.01 {
      our const @ISA = ('MyBase');
    }

    # open call. MyChild is of type MyBase
    my MyBase $obj = MyChild->new;
    => MyBase::new()

When the left-hand side of a method call is typed, the result of the method call must be of this type or any dependent type (i.e., MyBase or MyChild). Since MyChild is constant, i.e. no &MyChild::new method can be added at run-time, and @MyChild::ISA is also constant, it can only be &MyBase::new, even if MyBase itself is not constant.

Lexical subs NYI

Lexically defined subs are private subs but public callable and optimizable methods

    package MyClass 0.01 {
      our @ISA = ();
      my sub new { bless { @_ }, shift }
      my $private; # pad in maincv
      our $open;   # in stash
    }

    ...
    package main;
    my $obj = new MyClass; # i.e MyClass->new is valid and optimized.
                           # Indirect method call syntax helps.

    my $obj = MyClass::new(); # invalid
    => Undefined subroutine &MyClass::new called

Since &MyClass::new is lexically defined in the package scope, the compiler may statically optimize all method calls to &MyClass::new to an improved entersub (the CV being on a pad) without namespace lookup and dynamic method resolution, without having to const %MyClass:: and const @MyClass::ISA.

Lexical definition guarantees compile-time definition, which is not overridable dynamically at run-time.

coretypes

The coretypes module implements efficient implementations of natively typed scalars, arrays and hashes (at least since 5.18), and the @ISA of the three coretypes are guaranteed to be empty. Thus there will no mother of all, such as a generic type object to override coretypes, but there will be softer children of coretypes to allow stringification and undef.

So it is safe to optimize coretypes to its native operations at compile-time.

See also "coretypes" in perldata for examples.

External type modules

External modules, such as types, typesafety or Moose, implement their type optimizations for the types they declare or allow declaration for during execution of "CHECK" in perlsub blocks.

XXX __PACKAGE__ types questionable

As convenience for module authors it was asked to allow declarations, like

    package MyClass;
    my __PACKAGE__ $obj = __PACKAGE__->new;

Currently only the right-hand side is valid Perl.

This looks awful though. Refactoring of the package name should really refactor the internal types also, besides the type of all library users. But it would be consistent. See http://www.perl.com/pub/2000/06/p5pdigest/THISWEEK-20000625.html#my___PACKAGE___obj_

SEE ALSO

See "Constant and typed lexical variables" in perldata for the syntax of Perl's built-in type declarations for variables, and "??? p5-mop design" for the syntax of Perl's argument and return type declarations.

http://perl.plover.com/classes/typing/ Strong Typing Doesn't Have to Suck

Something went wrong with that request. Please try again.