Lexical::Types - Extend the semantics of typed lexicals.


Lexical-Types documentation Contained in the Lexical-Types distribution.

Index


Code Index:

NAME

Top

Lexical::Types - Extend the semantics of typed lexicals.

VERSION

Top

Version 0.11

SYNOPSIS

Top

    { package Str; }

    {
     package My::Types::Str;

     sub new { bless { }, shift }
    }

    use Lexical::Types as => sub { 'My::Types::' . $_[0] => 'new' };

    my Str $x; # $x is now a My::Types::Str object

    {
     package My::Types::Int;

     sub TYPEDSCALAR { bless { }, shift }
    }

    use Lexical::Types;

    use constant Int => 'My::Types::Int';

    my Int $y; # $y is now a My::Types::Int object

DESCRIPTION

Top

This pragma allows you to hook the execution of typed lexicals declarations (my Str $x) by calling a configurable method in a configurable package at each run. In particular, it can be used to automatically tie or bless typed lexicals whenever they are initialized.

Remind that for perl to be able to parse my Str $x, you need :

so make sure you follow one of those two strategies to define your types.

This pragma is not implemented with a source filter.

FUNCTIONS

Top

import [ as => [ $prefix | $mangler ] ]

Magically called when writing use Lexical::Types. All the occurences of my Str $x in the current lexical scope will be changed to call at each run a given method in a given package. The method and package are determined by the parameter 'as' :

unimport

Magically called when writing no Lexical::Types. Turns the pragma off.

RUN-TIME INITIALIZER METHOD

Top

The initializer method receives an alias to the pad slot of the initialized lexical in $_[1] and the original type name in $_[2]. You can either edit $_[1] in place, in which case you should return an empty list, or return a new scalar that will be copied into the pad slot.

    use Lexical::Types as => 'My';

    my Str $x;

    ...

    sub My::Str::TYPEDSCALAR {
     # $_[1] is an alias to $x, and $_[2] is 'Str'
     ...
    }

INTEGRATION

Top

You can integrate Lexical::Types in your module so that using it will provide types to your users without asking them to load either Lexical::Types or the type classes manually.

    package MyTypes;

    BEGIN { require Lexical::Types; }

    sub import {
     eval 'package Str; package Int'; # The types you want to support
     Lexical::Types->import(
      as => sub { __PACKAGE__, 'new_' . lc($_[0]) }
     );
    }

    sub unimport {
     Lexical::Types->unimport;
    }

    sub new_str { ... }

    sub new_int { ... }

If you prefer to use constants rather than creating empty packages, you can replace the previous example with something like this :

    package MyTypes;

    BEGIN { require Lexical::Types; }

    sub import {
     my $pkg = caller;
     for (qw<Str Int>) {
      my $type = __PACKAGE__ . '::' . $_;
      no strict 'refs';
      no warnings 'redefine';
      *{$pkg.'::'.$_} = eval "sub () { '$type' }";
     }
     Lexical::Types->import(
      as => sub { $_[0] => 'new' }
     );
    }

    sub unimport {
     Lexical::Types->unimport;
    }

    package MyTypes::Str;

    sub new { ... }

    package MyTypes::Int;

    sub new { ... }

CONSTANTS

Top

LT_THREADSAFE

True iff the module could have been built with thread-safety features enabled.

LT_FORKSAFE

True iff this module could have been built with fork-safety features enabled. This will always be true except on Windows where it's false for perl 5.10.0 and below .

CAVEATS

Top

The restrictions on the type (being either a defined package name or a constant) apply even if you use the 'as' option to redirect to another package, and are unlikely to find a workaround as this happens deep inside the lexer - far from the reach of an extension.

Only one mangler or prefix can be in use at the same time in a given scope.

The implementation was tweaked to work around several limitations of vanilla perl pragmas : it's thread safe, and doesn't suffer from a perl 5.8.x-5.10.0 bug that causes all pragmas to propagate into required scopes.

With 5.8 perls, the pragma does not propagate into eval STRING. This is due to a shortcoming in the way perl handles the hints hash, which is addressed in perl 5.10.

DEPENDENCIES

Top

perl 5.8.3.

A C compiler. This module may happen to build with a C++ compiler as well, but don't rely on it, as no guarantee is made in this regard.

XSLoader (standard since perl 5.006).

SEE ALSO

Top

fields.

Attribute::Handlers.

AUTHOR

Top

Vincent Pit, <perl at profvince.com>, http://www.profvince.com.

You can contact me by mail or on irc.perl.org (vincent).

BUGS

Top

Please report any bugs or feature requests to bug-lexical-types at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Lexical-Types. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

SUPPORT

Top

You can find documentation for this module with the perldoc command.

    perldoc Lexical::Types

Tests code coverage report is available at http://www.profvince.com/perl/cover/Lexical-Types.

ACKNOWLEDGEMENTS

Top

Inspired by Ricardo Signes.

Thanks Florian Ragwitz for suggesting the use of constants for types.

COPYRIGHT & LICENSE

Top


Lexical-Types documentation Contained in the Lexical-Types distribution.
package Lexical::Types;

use 5.008003;

use strict;
use warnings;

our $VERSION;
BEGIN {
 $VERSION = '0.11';
}

BEGIN {
 require XSLoader;
 XSLoader::load(__PACKAGE__, $VERSION);
}

sub import {
 shift;
 my %args = @_;

 my $hint;

 my $as = delete $args{'as'};
 if ($as) {
  my $r = ref $as;
  if ($r eq 'CODE') {
   $hint = _tag($as);
  } elsif (!$r) {
   $as .= '::' if $as !~ /::$/;
   $hint = _tag(sub { $as . $_[0] });
  } else {
   require Carp;
   Carp::croak("Invalid $r reference for 'as'");
  }
 } else {
  $hint = _tag(sub { @_ });
 }

 $^H |= 0x020000;
 # Yes, we store a coderef inside the hints hash, but that's just for compile
 # time.
 $^H{+(__PACKAGE__)} = $hint;
}

sub unimport {
 $^H{+(__PACKAGE__)} = undef;
}

1; # End of Lexical::Types