--- 
author: 
  email: rafl@fsfe.org
  keyid: 742f2a428e635a5e
  name: Florian Ragwitz
categories: 
  - Perl
date: 2009-04-28T06:09:31Z
guid: 97a76a6d-4019-4554-9993-2de23bde7e39
modified: 2009-04-28T06:20:16Z
raw: "-----BEGIN PGP SIGNED MESSAGE-----\nHash: SHA1\n\n=pod\n\nFor quite some time perl provided a form of C<my> declarations that\nincludes a type name, like this:\n\n  lang:Perl\n  my Str $x = 'foo';\n\nHowever, that didn't do anything useful, until Vincent Pit came along\nand wrote the excellent\nL<Lexical::Types|http://search.cpan.org/perldoc?Lexical::Types>\nmodule, which allows you to extend the semantics of typed lexicals and\nactually make them do something useful. For that, it simply invokes a\ncallback for every C<my> declaration with a type in the scopes it is\nloaded. Within that callback you get the variable that is being\ndeclared as well as the name of the type used in the declaration.\n\nWe also have Moose type constraints and the great\nL<MooseX::Types|http://search.cpan.org/perldoc?MooseX::Types> module,\nthat allows us to define our own type libraries and import the type\nconstraints into other modules.\n\nLet's glue those modules together. Consider this code:\n\n  lang:Perl\n  use MooseX::Types::Moose qw/Int/;\n  use Lexical::Types;\n  my Int $x = 42;\n\nThe first problem is that the perl compiler expects a package with the\nname of the type used in C<my> to exist. If there's no such package\ncompilation will fail.\n\nCreating top-level namespaces for all the types we want to use would\nobviously suck. Luckily the compiler will also try to look for a\nfunction with the name of the type in the current scope. If that\nexists and is inlineable, it will call that function and use the\nreturn value as a package name.\n\nIn the above code snippet an C<Int> function already exists. We\nimported that from C<MooseX::Types::Moose>. Unfortunately it isn't\ninlineable. Even if it were, compilation would still fail, because it\nwould return a C<Moose::Meta::TypeConstraint> instead of a valid\npackage name.\n\nTo fix that, let's rewrite the code to this:\n\n  lang:Perl\n  use MooseX::Types::Moose qw/Int/;\n  use MooseX::Lexical::Types qw/Int/;\n  my Int $x = 42;\n\nLet's also write a MooseX::Lexical::Types module that replaces\nexisting imported type exports with something that can be inlined and\nreturns an existing package name based on the type constraint's name.\n\n  lang:Perl\n  package MooseX::Lexical::Types;\n\n  use Class::MOP;\n  use MooseX::Types::Util qw/has_available_type_export/;\n  use namespace::autoclean;\n\n  sub import {\n      my ($class, @args) = @_;\n      my $caller = caller();\n\n      my $meta = Class::MOP::class_of($caller) || Class::MOP::Class->initialize($caller);\n\n      for my $type_name (@args) {\n          # get the type constraint by introspecting the caller\n          my $type_constraint = has_available_type_export($caller, $type_name);\n\n          my $package = 'MooseX::Lexical::Types::TYPE::' . $type_constraint->name;\n          Class::MOP::Class->create($package);\n          $meta->add_package_symbol('&'.$type_name => sub () { $package });\n      }\n\n      Lexical::Types->import; # enable Lexical::Types for the caller\n  }\n\n  1;\n\nWith that the example code now compiles. Unfortunately it breaks every\nother usecase of MooseX::Types. The export will still need to return a\nC<Moose::Meta::TypeConstraint> at run time so this will continue to\nwork:\n\n  lang:Perl\n  has some_attribute => (is => 'ro', isa => Int);\n\nSo instead of returning a plain package name from our exported\nfunction we will return an object that delegates all method calls to\nthe actual type constraint, but evaluates to our special package name\nwhen used as a string:\n\n  lang:Perl\n  my $decorator = MooseX::Lexical::Types::TypeDecorator->new($type_constraint);\n  $meta->add_package_symbol('&'.$type_name => sub () { $decorator });\n\nand:\n\n  lang:Perl\n  package MooseX::Lexical::Types::TypeDecorator;\n  use Moose;\n  use namespace::autoclean;\n\n  # MooseX::Types happens to already have a class that doesn't do much\n  # more than delegating to a real type constraint!\n  extends 'MooseX::Types::TypeDecorator';\n\n  use overload '\"\"' => sub {\n      'MooseX::Lexical::Types::TYPE::' . $_[0]->__type_constraint->name\n  };\n\n  1;\n\nNow we're able to use C<Int> as usual and have Lexical::Types invoke\nits callback on C<MooseX::Lexical::Types::TYPE::Int>. Within that\ncallback we will need the real type constraint again, but as it is\ninvoked as a class method with no good way to pass in additional\narguments, we will need to store the type constraint somewhere. I\nchoose to simply add a method to the type class we create when\nconstructing our export. After that, all we need is to implement our\nLexical::Types callback. We will put that in a class all our type\nclasses will inherit from:\n\n  lang:Perl\n  Class::MOP::Class->create(\n      $package => (\n          superclasses => ['MooseX::Lexical::Types::TypedScalar'],\n          methods      => {\n              get_type_constraint => sub { $type_constraint },\n          },\n      ),\n  );\n\nThe Lexical::Types callback will now need to tie things together by\nmodifying the declared variable so it will automatically validate\nvalues against the type constraint when being assigned to. There are\nseveral ways of doing this. Using C<tie> on the declared variable\nwould probable be the easiest thing to do. However, I decided to use\nL<Variable::Magic|http://search.cpan.org/perldoc?Variable::Magic>\n(also written by Vincent Pit - did I mention he's awesome?), because\nit's mostly invisible at the perl level and also performs rather well\n(not that it'd matter, given that validation itself is relatively\nslow):\n\n  lang:Perl\n  package MooseX::Lexical::Types::TypedScalar;\n\n  use Carp qw/confess/;\n  use Variable::Magic qw/wizard cast/;\n  use namespace::autoclean;\n\n  my $wiz = wizard\n      # store the type constraint in the data attached to the magic\n      data => sub { $_[1]->get_type_constraint },\n      # when assigning to the variable, fail if we can't validate the\n      # new value ($_[0]) against the type constraint ($_[1])\n      set  => sub {\n          if (defined (my $msg = $_[1]->validate(${ $_[0] }))) {\n              confess $msg;\n          }\n          ();\n      };\n\n  sub TYPEDSCALAR {\n      # cast $wiz on the variable in $_[1]. pass the type package name\n      # in $_[0] to the wizard's data construction callback.\n      cast $_[1], $wiz, $_[0];\n      ();\n  }\n\n  1;\n\nWith this, our example code now works. If someone wants to assign,\nsay, C<'foo'> to the variable declared as C<my Int $x> our magic\ncallback will be invoked, try to validate the value against the type\nconstraint and fail loudly. B<WIN!>\n\nThe code for all this is available\nL<github|http://github.com/rafl/moosex-lexical-types> and should also\nbe on CPAN shortly.\n\nYou might notice warnings about mismatching prototypes. Those are\ncaused by Class::MOP and fixed in the git version of it, so they'll go\naway with the next release.\n\nThere's still a couple of caveats, but please see L<the\ndocumentation|http://search.cpan.org/perldoc?MooseX::Lexical::Types>\nfor that.\n\n=cut\n-----BEGIN PGP SIGNATURE-----\nVersion: GnuPG v1.4.6 (GNU/Linux)\n\niD8DBQFJ9qAgdC8qQo5jWl4RAni9AJoDwsG/8iNd2MlXvBLG6+1IOXCCnwCfZnys\nuUwBX0DArfYxN0EJf48Op2w=\n=xSW5\n-----END PGP SIGNATURE-----\n"
signed: 1
summary: " For quite some time perl provided a form of …"
tags: 
  - 
    perl: 0
  - 
    types: 0
  - 
    moose: 0
  - 
    syntax: 0
text: "    For quite some time perl provided a form of my declarations that in-\n    cludes a type name, like this:\n\n      lang:Perl my Str $x = 'foo';\n\n    However, that didn't do anything useful, until Vincent Pit came a-\n    long and wrote the excellent Lexical::Types module, which allows you\n    to extend the semantics of typed lexicals and actually make them do\n    something useful. For that, it simply invokes a callback for every\n    my declaration with a type in the scopes it is loaded. Within that\n    callback you get the variable that is being declared as well as the\n    name of the type used in the declaration.\n\n    We also have Moose type constraints and the great MooseX::Types mod-\n    ule, that allows us to define our own type libraries and import the\n    type constraints into other modules.\n\n    Let's glue those modules together. Consider this code:\n\n      lang:Perl use MooseX::Types::Moose qw/Int/; use Lexical::Types; my\n      Int $x = 42;\n\n    The first problem is that the perl compiler expects a package with\n    the name of the type used in my to exist. If there's no such package\n    compilation will fail.\n\n    Creating top-level namespaces for all the types we want to use would\n    obviously suck. Luckily the compiler will also try to look for a\n    function with the name of the type in the current scope. If that ex-\n    ists and is inlineable, it will call that function and use the re-\n    turn value as a package name.\n\n    In the above code snippet an Int function already exists. We im-\n    ported that from MooseX::Types::Moose. Unfortunately it isn't in-\n    lineable. Even if it were, compilation would still fail, because\n    it would return a Moose::Meta::TypeConstraint instead of a valid\n    package name.\n\n    To fix that, let's rewrite the code to this:\n\n      lang:Perl use MooseX::Types::Moose qw/Int/; use MooseX::Lexi-\n      cal::Types qw/Int/; my Int $x = 42;\n\n    Let's also write a MooseX::Lexical::Types module that replaces\n    existing imported type exports with something that can be in-\n    lined and returns an existing package name based on the type\n    constraint's name.\n\n      lang:Perl package MooseX::Lexical::Types;\n\n      use Class::MOP; use MooseX::Types::Util qw/has_available_type_ex-\n      port/; use namespace::autoclean;\n\n      sub import { my ($class, @args) = @_; my $caller = caller();\n\n          my $meta = Class::MOP::class_of($caller) ||\n          Class::MOP::Class->initialize($caller);\n\n          for my $type_name (@args) {\n              # get the type constraint by introspecting the caller\n              my $type_constraint = has_available_type_export($caller,\n              $type_name);\n\n              my $package = 'MooseX::Lexical::Types::TYPE::' . $type_-\n              constraint->name; Class::MOP::Class->create($package);\n              $meta->add_package_symbol('&'.$type_name => sub () { $-\n              package }); }\n\n          Lexical::Types->import; # enable Lexical::Types for the caller\n          }\n\n      1;\n\n    With that the example code now compiles. Unfortunately it breaks ev-\n    ery other usecase of MooseX::Types. The export will still need to\n    return a Moose::Meta::TypeConstraint at run time so this will con-\n    tinue to work:\n\n      lang:Perl has some_attribute => (is => 'ro', isa => Int);\n\n    So instead of returning a plain package name from our exported func-\n    tion we will return an object that delegates all method calls to the\n    actual type constraint, but evaluates to our special package name\n    when used as a string:\n\n      lang:Perl my $decorator = MooseX::Lexical::Types::TypeDecora-\n      tor->new($type_constraint); $meta->add_package_symbol('&'.$type_-\n      name => sub () { $decorator });\n\n    and:\n\n      lang:Perl package MooseX::Lexical::Types::TypeDecorator; use\n      Moose; use namespace::autoclean;\n\n      # MooseX::Types happens to already have a class that doesn't do\n      # much more than delegating to a real type constraint!\n      extends 'MooseX::Types::TypeDecorator';\n\n      use overload '\"\"' => sub { 'MooseX::Lexical::Types::TYPE::' .\n      $_[0]->__type_constraint->name };\n\n      1;\n\n    Now we're able to use Int as usual and have Lexical::Types invoke\n    its callback on MooseX::Lexical::Types::TYPE::Int. Within that call-\n    back we will need the real type constraint again, but as it is in-\n    voked as a class method with no good way to pass in additional argu-\n    ments, we will need to store the type constraint somewhere. I choose\n    to simply add a method to the type class we create when constructing\n    our export. After that, all we need is to implement our Lexi-\n    cal::Types callback. We will put that in a class all our type class-\n    es will inherit from:\n\n      lang:Perl Class::MOP::Class->create( $package => ( superclasses =>\n      ['MooseX::Lexical::Types::TypedScalar'], methods => { get_type_-\n      constraint => sub { $type_constraint }, }, ), );\n\n    The Lexical::Types callback will now need to tie things together by\n    modifying the declared variable so it will automatically validate\n    values against the type constraint when being assigned to. There are\n    several ways of doing this. Using tie on the declared variable would\n    probable be the easiest thing to do. However, I decided to use Vari-\n    able::Magic (also written by Vincent Pit - did I mention he's awe-\n    some?), because it's mostly invisible at the perl level and also\n    performs rather well (not that it'd matter, given that validation\n    itself is relatively slow):\n\n      lang:Perl package MooseX::Lexical::Types::TypedScalar;\n\n      use Carp qw/confess/; use Variable::Magic qw/wizard cast/; use\n      namespace::autoclean;\n\n      my $wiz = wizard\n          # store the type constraint in the data attached to the magic\n          data => sub { $_[1]->get_type_constraint },\n          # when assigning to the variable, fail if we can't validate\n          # the new value ($_[0]) against the type constraint ($_[1])\n          set => sub { if (defined (my $msg = $_[1]->validate(${ $_[0]\n          }))) { confess $msg; } (); };\n\n      sub TYPEDSCALAR {\n          # cast $wiz on the variable in $_[1]. pass the type package\n          # name in $_[0] to the wizard's data construction callback.\n          cast $_[1], $wiz, $_[0]; (); }\n\n      1;\n\n    With this, our example code now works. If someone wants to assign,\n    say, 'foo' to the variable declared as my Int $x our magic callback\n    will be invoked, try to validate the value against the type con-\n    straint and fail loudly. WIN!\n\n    The code for all this is available github and should also be on\n    CPAN shortly.\n\n    You might notice warnings about mismatching prototypes. Those are\n    caused by Class::MOP and fixed in the git version of it, so they'll\n    go away with the next release.\n\n    There's still a couple of caveats, but please see the documenta-\n    tion for that.\n"
title: Implementing Typed Lexical Variables
type: pod
uri: http://perldition.org/articles/Implementing%20Typed%20Lexical%20Variables.pod
xhtml: "<div class=\"pod\">\n<p>For quite some time perl provided a form of <code>my</code> declarations that\nincludes a type name, like this:</p>\n<pre><span class=\"Keyword\">my</span><span class=\"Normal\"> Str </span><span class=\"DataType\">$x</span><span class=\"Normal\"> = </span><span class=\"Operator\">&apos;</span><span class=\"String\">foo</span><span class=\"Operator\">&apos;</span><span class=\"Normal\">;</span>\n</pre>\n<p>However, that didn't do anything useful, until Vincent Pit came along\nand wrote the excellent\n<a href=\"http://search.cpan.org/perldoc?Lexical::Types\">Lexical::Types</a>\nmodule, which allows you to extend the semantics of typed lexicals and\nactually make them do something useful. For that, it simply invokes a\ncallback for every <code>my</code> declaration with a type in the scopes it is\nloaded. Within that callback you get the variable that is being\ndeclared as well as the name of the type used in the declaration.</p>\n<p>We also have Moose type constraints and the great\n<a href=\"http://search.cpan.org/perldoc?MooseX::Types\">MooseX::Types</a> module,\nthat allows us to define our own type libraries and import the type\nconstraints into other modules.</p>\n<p>Let's glue those modules together. Consider this code:</p>\n<pre><span class=\"Keyword\">use</span><span class=\"Normal\"> </span><span class=\"Function\">MooseX::Types</span><span class=\"Normal\">::</span><span class=\"Function\">Moose</span><span class=\"Normal\"> </span><span class=\"Operator\">qw/</span><span class=\"Normal\">Int</span><span class=\"Operator\">/</span><span class=\"Normal\">;</span><span class=\"Normal\">\n</span><span class=\"Keyword\">use</span><span class=\"Normal\"> </span><span class=\"Function\">Lexical::Types</span><span class=\"Normal\">;</span><span class=\"Normal\">\n</span><span class=\"Keyword\">my</span><span class=\"Normal\"> </span><span class=\"Function\">Int</span><span class=\"Normal\"> </span><span class=\"DataType\">$x</span><span class=\"Normal\"> = 42;</span>\n</pre>\n<p>The first problem is that the perl compiler expects a package with the\nname of the type used in <code>my</code> to exist. If there's no such package\ncompilation will fail.</p>\n<p>Creating top-level namespaces for all the types we want to use would\nobviously suck. Luckily the compiler will also try to look for a\nfunction with the name of the type in the current scope. If that\nexists and is inlineable, it will call that function and use the\nreturn value as a package name.</p>\n<p>In the above code snippet an <code>Int</code> function already exists. We\nimported that from <code>MooseX::Types::Moose</code>. Unfortunately it isn't\ninlineable. Even if it were, compilation would still fail, because it\nwould return a <code>Moose::Meta::TypeConstraint</code> instead of a valid\npackage name.</p>\n<p>To fix that, let's rewrite the code to this:</p>\n<pre><span class=\"Keyword\">use</span><span class=\"Normal\"> </span><span class=\"Function\">MooseX::Types</span><span class=\"Normal\">::</span><span class=\"Function\">Moose</span><span class=\"Normal\"> </span><span class=\"Operator\">qw/</span><span class=\"Normal\">Int</span><span class=\"Operator\">/</span><span class=\"Normal\">;</span><span class=\"Normal\">\n</span><span class=\"Keyword\">use</span><span class=\"Normal\"> </span><span class=\"Function\">MooseX::Lexical</span><span class=\"Normal\">::</span><span class=\"Function\">Types</span><span class=\"Normal\"> </span><span class=\"Operator\">qw/</span><span class=\"Normal\">Int</span><span class=\"Operator\">/</span><span class=\"Normal\">;</span><span class=\"Normal\">\n</span><span class=\"Keyword\">my</span><span class=\"Normal\"> </span><span class=\"Function\">Int</span><span class=\"Normal\"> </span><span class=\"DataType\">$x</span><span class=\"Normal\"> = 42;</span>\n</pre>\n<p>Let's also write a MooseX::Lexical::Types module that replaces\nexisting imported type exports with something that can be inlined and\nreturns an existing package name based on the type constraint's name.</p>\n<pre><span class=\"Keyword\">package</span><span class=\"Normal\"> </span><span class=\"Function\">MooseX::Lexical</span><span class=\"Normal\">::</span><span class=\"Function\">Types</span><span class=\"Normal\">;</span>\n\n<span class=\"Keyword\">use</span><span class=\"Normal\"> </span><span class=\"Function\">Class::MOP</span><span class=\"Normal\">;</span><span class=\"Normal\">\n</span><span class=\"Keyword\">use</span><span class=\"Normal\"> </span><span class=\"Function\">MooseX::Types</span><span class=\"Normal\">::</span><span class=\"Function\">Util</span><span class=\"Normal\"> </span><span class=\"Operator\">qw/</span><span class=\"Normal\">has_available_type_export</span><span class=\"Operator\">/</span><span class=\"Normal\">;</span><span class=\"Normal\">\n</span><span class=\"Keyword\">use</span><span class=\"Normal\"> </span><span class=\"Function\">namespace::autoclean</span><span class=\"Normal\">;</span>\n\n<span class=\"Keyword\">sub </span><span class=\"Function\">import</span><span class=\"Normal\"> {</span><span class=\"Normal\">\n</span><span class=\"Normal\">    </span><span class=\"Keyword\">my</span><span class=\"Normal\"> (</span><span class=\"DataType\">$class</span><span class=\"Normal\">, </span><span class=\"DataType\">@args</span><span class=\"Normal\">) = </span><span class=\"DataType\">@_</span><span class=\"Normal\">;</span><span class=\"Normal\">\n</span><span class=\"Normal\">    </span><span class=\"Keyword\">my</span><span class=\"Normal\"> </span><span class=\"DataType\">$caller</span><span class=\"Normal\"> = </span><span class=\"Function\">caller</span><span class=\"Normal\">();</span>\n\n<span class=\"Normal\">    </span><span class=\"Keyword\">my</span><span class=\"Normal\"> </span><span class=\"DataType\">$meta</span><span class=\"Normal\"> = </span><span class=\"Function\">Class::MOP</span><span class=\"Normal\">::</span><span class=\"Function\">class_of</span><span class=\"Normal\">(</span><span class=\"DataType\">$</span><span class=\"Normal\">caller) || </span><span class=\"Function\">Class::MOP</span><span class=\"Normal\">::</span><span class=\"Function\">Class</span><span class=\"Normal\">-&gt;initialize(</span><span class=\"DataType\">$caller</span><span class=\"Normal\">);</span>\n\n<span class=\"Normal\">    </span><span class=\"Keyword\">for</span><span class=\"Normal\"> </span><span class=\"Keyword\">my</span><span class=\"Normal\"> </span><span class=\"DataType\">$type_name</span><span class=\"Normal\"> (</span><span class=\"DataType\">@args</span><span class=\"Normal\">) {</span><span class=\"Normal\">\n</span><span class=\"Normal\">        </span><span class=\"Comment\"># get the type constraint by introspecting the caller</span><span class=\"Comment\">\n</span><span class=\"Normal\">        </span><span class=\"Keyword\">my</span><span class=\"Normal\"> </span><span class=\"DataType\">$type_constraint</span><span class=\"Normal\"> = has_available_type_export(</span><span class=\"DataType\">$caller</span><span class=\"Normal\">, </span><span class=\"DataType\">$type_name</span><span class=\"Normal\">);</span>\n\n<span class=\"Normal\">        </span><span class=\"Keyword\">my</span><span class=\"Normal\"> </span><span class=\"DataType\">$package</span><span class=\"Normal\"> = </span><span class=\"Operator\">&apos;</span><span class=\"String\">MooseX::Lexical::Types::TYPE::</span><span class=\"Operator\">&apos;</span><span class=\"Normal\"> . </span><span class=\"DataType\">$type_constraint</span><span class=\"Normal\">-&gt;</span><span class=\"DataType\">name</span><span class=\"Normal\">;</span><span class=\"Normal\">\n</span><span class=\"Normal\">        </span><span class=\"Function\">Class::MOP</span><span class=\"Normal\">::</span><span class=\"Function\">Class</span><span class=\"Normal\">-&gt;create(</span><span class=\"DataType\">$package</span><span class=\"Normal\">);</span><span class=\"Normal\">\n</span><span class=\"Normal\">        </span><span class=\"DataType\">$meta</span><span class=\"Normal\">-&gt;</span><span class=\"DataType\">add_package_symbol</span><span class=\"Normal\">(</span><span class=\"Operator\">&apos;</span><span class=\"String\">&amp;</span><span class=\"Operator\">&apos;</span><span class=\"Normal\">.</span><span class=\"DataType\">$type_name</span><span class=\"Normal\"> =&gt; </span><span class=\"Keyword\">sub </span><span class=\"Normal\">() { </span><span class=\"DataType\">$package</span><span class=\"Normal\"> });</span><span class=\"Normal\">\n</span><span class=\"Normal\">    }</span>\n\n<span class=\"Normal\">    </span><span class=\"Function\">Lexical::Types</span><span class=\"Normal\">-&gt;</span><span class=\"Function\">import</span><span class=\"Normal\">; </span><span class=\"Comment\"># enable Lexical::Types for the caller</span><span class=\"Comment\">\n</span><span class=\"Normal\">}</span>\n\n<span class=\"Float\">1</span><span class=\"Normal\">;</span>\n</pre>\n<p>With that the example code now compiles. Unfortunately it breaks every\nother usecase of MooseX::Types. The export will still need to return a\n<code>Moose::Meta::TypeConstraint</code> at run time so this will continue to\nwork:</p>\n<pre><span class=\"Normal\">has some_attribute =&gt; (is =&gt; </span><span class=\"Operator\">&apos;</span><span class=\"String\">ro</span><span class=\"Operator\">&apos;</span><span class=\"Normal\">, isa =&gt; </span><span class=\"Function\">Int</span><span class=\"Normal\">);</span>\n</pre>\n<p>So instead of returning a plain package name from our exported\nfunction we will return an object that delegates all method calls to\nthe actual type constraint, but evaluates to our special package name\nwhen used as a string:</p>\n<pre><span class=\"Keyword\">my</span><span class=\"Normal\"> </span><span class=\"DataType\">$decorator</span><span class=\"Normal\"> = </span><span class=\"Function\">MooseX::Lexical</span><span class=\"Normal\">::</span><span class=\"Function\">Types</span><span class=\"Normal\">::</span><span class=\"Function\">TypeDecorator</span><span class=\"Normal\">-&gt;new(</span><span class=\"DataType\">$type_constraint</span><span class=\"Normal\">);</span><span class=\"Normal\">\n</span><span class=\"DataType\">$meta</span><span class=\"Normal\">-&gt;</span><span class=\"DataType\">add_package_symbol</span><span class=\"Normal\">(</span><span class=\"Operator\">&apos;</span><span class=\"String\">&amp;</span><span class=\"Operator\">&apos;</span><span class=\"Normal\">.</span><span class=\"DataType\">$type_name</span><span class=\"Normal\"> =&gt; </span><span class=\"Keyword\">sub </span><span class=\"Normal\">() { </span><span class=\"DataType\">$decorator</span><span class=\"Normal\"> });</span>\n</pre>\n<p>and:</p>\n<pre><span class=\"Keyword\">package</span><span class=\"Normal\"> </span><span class=\"Function\">MooseX::Lexical</span><span class=\"Normal\">::</span><span class=\"Function\">Types</span><span class=\"Normal\">::</span><span class=\"Function\">TypeDecorator</span><span class=\"Normal\">;</span><span class=\"Normal\">\n</span><span class=\"Keyword\">use</span><span class=\"Normal\"> Moose;</span><span class=\"Normal\">\n</span><span class=\"Keyword\">use</span><span class=\"Normal\"> </span><span class=\"Function\">namespace::autoclean</span><span class=\"Normal\">;</span>\n\n<span class=\"Comment\"># MooseX::Types happens to already have a class that doesn&apos;t do much</span><span class=\"Comment\">\n</span><span class=\"Comment\"># more than delegating to a real type constraint!</span><span class=\"Comment\">\n</span><span class=\"Normal\">extends </span><span class=\"Operator\">&apos;</span><span class=\"String\">MooseX::Types::TypeDecorator</span><span class=\"Operator\">&apos;</span><span class=\"Normal\">;</span>\n\n<span class=\"Keyword\">use</span><span class=\"Normal\"> overload </span><span class=\"Operator\">&apos;</span><span class=\"String\">&quot;&quot;</span><span class=\"Operator\">&apos;</span><span class=\"Normal\"> =&gt; </span><span class=\"Keyword\">sub </span><span class=\"Normal\">{</span><span class=\"Normal\">\n</span><span class=\"Normal\">    </span><span class=\"Operator\">&apos;</span><span class=\"String\">MooseX::Lexical::Types::TYPE::</span><span class=\"Operator\">&apos;</span><span class=\"Normal\"> . </span><span class=\"Variable\">$_</span><span class=\"Normal\">[0]</span><span class=\"Operator\">-</span><span class=\"Normal\">&gt;__type_constraint-&gt;name</span><span class=\"Normal\">\n</span><span class=\"Normal\">};</span>\n\n<span class=\"Float\">1</span><span class=\"Normal\">;</span>\n</pre>\n<p>Now we're able to use <code>Int</code> as usual and have Lexical::Types invoke\nits callback on <code>MooseX::Lexical::Types::TYPE::Int</code>. Within that\ncallback we will need the real type constraint again, but as it is\ninvoked as a class method with no good way to pass in additional\narguments, we will need to store the type constraint somewhere. I\nchoose to simply add a method to the type class we create when\nconstructing our export. After that, all we need is to implement our\nLexical::Types callback. We will put that in a class all our type\nclasses will inherit from:</p>\n<pre><span class=\"Function\">Class::MOP</span><span class=\"Normal\">::</span><span class=\"Function\">Class</span><span class=\"Normal\">-&gt;create(</span><span class=\"Normal\">\n</span><span class=\"Normal\">    </span><span class=\"DataType\">$package</span><span class=\"Normal\"> =&gt; (</span><span class=\"Normal\">\n</span><span class=\"Normal\">        superclasses =&gt; [</span><span class=\"Operator\">&apos;</span><span class=\"String\">MooseX::Lexical::Types::TypedScalar</span><span class=\"Operator\">&apos;</span><span class=\"Normal\">],</span><span class=\"Normal\">\n</span><span class=\"Normal\">        methods      =&gt; {</span><span class=\"Normal\">\n</span><span class=\"Normal\">            get_type_constraint =&gt; </span><span class=\"Keyword\">sub </span><span class=\"Normal\">{ </span><span class=\"DataType\">$type_constraint</span><span class=\"Normal\"> },</span><span class=\"Normal\">\n</span><span class=\"Normal\">        },</span><span class=\"Normal\">\n</span><span class=\"Normal\">    ),</span><span class=\"Normal\">\n</span><span class=\"Normal\">);</span>\n</pre>\n<p>The Lexical::Types callback will now need to tie things together by\nmodifying the declared variable so it will automatically validate\nvalues against the type constraint when being assigned to. There are\nseveral ways of doing this. Using <code>tie</code> on the declared variable\nwould probable be the easiest thing to do. However, I decided to use\n<a href=\"http://search.cpan.org/perldoc?Variable::Magic\">Variable::Magic</a>\n(also written by Vincent Pit - did I mention he's awesome?), because\nit's mostly invisible at the perl level and also performs rather well\n(not that it'd matter, given that validation itself is relatively\nslow):</p>\n<pre><span class=\"Keyword\">package</span><span class=\"Normal\"> </span><span class=\"Function\">MooseX::Lexical</span><span class=\"Normal\">::</span><span class=\"Function\">Types</span><span class=\"Normal\">::</span><span class=\"Function\">TypedScalar</span><span class=\"Normal\">;</span>\n\n<span class=\"Keyword\">use</span><span class=\"Normal\"> Carp </span><span class=\"Operator\">qw/</span><span class=\"Normal\">confess</span><span class=\"Operator\">/</span><span class=\"Normal\">;</span><span class=\"Normal\">\n</span><span class=\"Keyword\">use</span><span class=\"Normal\"> </span><span class=\"Function\">Variable::Magic</span><span class=\"Normal\"> </span><span class=\"Operator\">qw/</span><span class=\"Normal\">wizard cast</span><span class=\"Operator\">/</span><span class=\"Normal\">;</span><span class=\"Normal\">\n</span><span class=\"Keyword\">use</span><span class=\"Normal\"> </span><span class=\"Function\">namespace::autoclean</span><span class=\"Normal\">;</span>\n\n<span class=\"Keyword\">my</span><span class=\"Normal\"> </span><span class=\"DataType\">$wiz</span><span class=\"Normal\"> = wizard</span><span class=\"Normal\">\n</span><span class=\"Normal\">    </span><span class=\"Comment\"># store the type constraint in the data attached to the magic</span><span class=\"Comment\">\n</span><span class=\"Normal\">    data =&gt; </span><span class=\"Keyword\">sub </span><span class=\"Normal\">{ </span><span class=\"Variable\">$_</span><span class=\"Normal\">[</span><span class=\"Float\">1</span><span class=\"Normal\">]</span><span class=\"Operator\">-</span><span class=\"Normal\">&gt;get_type_constraint },</span><span class=\"Normal\">\n</span><span class=\"Normal\">    </span><span class=\"Comment\"># when assigning to the variable, fail if we can&apos;t validate the</span><span class=\"Comment\">\n</span><span class=\"Normal\">    </span><span class=\"Comment\"># new value ($_[0]) against the type constraint ($_[1])</span><span class=\"Comment\">\n</span><span class=\"Normal\">    set  =&gt; </span><span class=\"Keyword\">sub </span><span class=\"Normal\">{</span><span class=\"Normal\">\n</span><span class=\"Normal\">        </span><span class=\"Keyword\">if</span><span class=\"Normal\"> (</span><span class=\"Function\">defined</span><span class=\"Normal\"> (</span><span class=\"Keyword\">my</span><span class=\"Normal\"> </span><span class=\"DataType\">$msg</span><span class=\"Normal\"> = </span><span class=\"Variable\">$_</span><span class=\"Normal\">[</span><span class=\"Float\">1</span><span class=\"Normal\">]</span><span class=\"Operator\">-</span><span class=\"Normal\">&gt;validate(</span><span class=\"DataType\">$</span><span class=\"Normal\">{ </span><span class=\"Variable\">$_</span><span class=\"Normal\">[0] }))) {</span><span class=\"Normal\">\n</span><span class=\"Normal\">            confess </span><span class=\"DataType\">$msg</span><span class=\"Normal\">;</span><span class=\"Normal\">\n</span><span class=\"Normal\">        }</span><span class=\"Normal\">\n</span><span class=\"Normal\">        ();</span><span class=\"Normal\">\n</span><span class=\"Normal\">    };</span>\n\n<span class=\"Keyword\">sub </span><span class=\"Function\">TYPEDSCALAR</span><span class=\"Normal\"> {</span><span class=\"Normal\">\n</span><span class=\"Normal\">    </span><span class=\"Comment\"># cast $wiz on the variable in $_[1]. pass the type package name</span><span class=\"Comment\">\n</span><span class=\"Normal\">    </span><span class=\"Comment\"># in $_[0] to the wizard&apos;s data construction callback.</span><span class=\"Comment\">\n</span><span class=\"Normal\">    cast </span><span class=\"Variable\">$_</span><span class=\"Normal\">[</span><span class=\"Float\">1</span><span class=\"Normal\">], </span><span class=\"DataType\">$wiz</span><span class=\"Normal\">, </span><span class=\"Variable\">$_</span><span class=\"Normal\">[0];</span><span class=\"Normal\">\n</span><span class=\"Normal\">    ();</span><span class=\"Normal\">\n</span><span class=\"Normal\">}</span>\n\n<span class=\"Float\">1</span><span class=\"Normal\">;</span>\n</pre>\n<p>With this, our example code now works. If someone wants to assign,\nsay, <code>'foo'</code> to the variable declared as <code>my Int $x</code> our magic\ncallback will be invoked, try to validate the value against the type\nconstraint and fail loudly. <strong>WIN!</strong></p>\n<p>The code for all this is available\n<a href=\"http://github.com/rafl/moosex-lexical-types\">github</a> and should also\nbe on CPAN shortly.</p>\n<p>You might notice warnings about mismatching prototypes. Those are\ncaused by Class::MOP and fixed in the git version of it, so they'll go\naway with the next release.</p>\n<p>There's still a couple of caveats, but please see <a href=\"http://search.cpan.org/perldoc?MooseX::Lexical::Types\">the documentation</a>\nfor that.</p>\n\n\n</div>"
