fix documentation of type heirarchy
[gitmo/Moose.git] / lib / Moose / Manual / Types.pod
index d743b3d..1b54e65 100644 (file)
@@ -1,8 +1,10 @@
-=pod
+package Moose::Manual::Types;
+
+# ABSTRACT: Moose's type system
 
-=head1 NAME
+__END__
 
-Moose::Manual::Types - Moose's type system
+=pod
 
 =head1 TYPES IN PERL?
 
@@ -11,17 +13,16 @@ these types to validate method parameters with the help of a MooseX
 module.
 
 Moose's type system is based on a combination of Perl 5's own
-I<implicit> types and some Perl 6 concepts. You can easily create your
+I<implicit> types and some Perl 6 concepts. You can create your
 own subtypes with custom constraints, making it easy to express any
 sort of validation.
 
 Types have names, and you can re-use them by name, making it easy to
 share types throughout a large application.
 
-Let us be clear that is not a "real" type system. Moose does not
-magically make Perl start associating types with variables. This is
-just an advanced parameter checking system which allows you to
-associate a name with a constraint.
+However, this is not a "real" type system. Moose does not magically make Perl
+start associating types with variables. This is just an advanced parameter
+checking system which allows you to associate a name with a constraint.
 
 That said, it's still pretty damn useful, and we think it's one of the
 things that makes Moose both fun and powerful. Taking advantage of the
@@ -33,33 +34,60 @@ data, and it also contributes greatly to code maintainability.
 The basic Moose type hierarchy looks like this
 
   Any
-  Item
-      Bool
-      Maybe[`a]
-      Undef
-      Defined
-          Value
-              Num
-                Int
-              Str
-                ClassName
-          Ref
-              ScalarRef
-              ArrayRef[`a]
-              HashRef[`a]
-              CodeRef
-              RegexpRef
-              GlobRef
-                FileHandle
-              Object
-                Role
+      Item
+          Bool
+          Maybe[`a]
+          Undef
+          Defined
+              Value
+                  Str
+                      Num
+                          Int
+                      ClassName
+                      RoleName
+              Ref
+                  ScalarRef[`a]
+                  ArrayRef[`a]
+                  HashRef[`a]
+                  CodeRef
+                  RegexpRef
+                  GlobRef
+                  FileHandle
+                  Object
 
 In practice, the only difference between C<Any> and C<Item> is
 conceptual. C<Item> is used as the top-level type in the hierarchy.
 
-The rest of these types correspond to existing Perl concepts. For
-example, a C<Num> is anything that Perl thinks looks like a number. An
-C<Object> is a blessed reference, etc.
+The rest of these types correspond to existing Perl concepts.
+In particular:
+
+=over 4
+
+=item
+
+C<Bool> accepts C<1> for true, and undef, 0, or the empty string as false.
+
+=item
+
+C<Maybe[`a]> accepts either C<`a> or C<undef>.
+
+=item
+
+C<Num> accepts anything that perl thinks looks like a number (see L<Scalar::Util/looks_like_number>).
+
+=item
+
+C<ClassName> and C<RoleName> accept strings that are either the name of a class or the name of a role. The class/role must already be loaded when the constraint is checked.
+
+=item
+
+C<FileHandle> accepts either an L<IO::Handle> object or a builtin perl filehandle (see L<Scalar::Util/openhandle>).
+
+=item
+
+C<Object> accepts any blessed reference.
+
+=back
 
 The types followed by "[`a]" can be parameterized. So instead of just
 plain C<ArrayRef> we can say that we want C<ArrayRef[Int]> instead. We
@@ -68,7 +96,7 @@ can even do something like C<HashRef[ArrayRef[Str]]>.
 The C<Maybe[`a]> type deserves a special mention. Used by itself, it
 doesn't really mean anything (and is equivalent to C<Item>). When it
 is parameterized, it means that the value is either C<undef> or the
-parameterized type. So C<Maybe[Int]> means an integer or C<undef>
+parameterized type. So C<Maybe[Int]> means an integer or C<undef>.
 
 For more details on the type hierarchy, see
 L<Moose::Util::TypeConstraints>.
@@ -78,7 +106,7 @@ L<Moose::Util::TypeConstraints>.
 It's important to realize that types are not classes (or
 packages). Types are just objects (L<Moose::Meta::TypeConstraint>
 objects, to be exact) with a name and a constraint. Moose maintains a
-global type registry that lets it convert names like "Num" into the
+global type registry that lets it convert names like C<Num> into the
 appropriate object.
 
 However, class names I<can be> type names. When you define a new class
@@ -91,7 +119,7 @@ using Moose, it defines an associated type name behind the scenes:
 Now you can use C<'MyApp::User'> as a type name:
 
   has creator => (
-      is  => 'rw',
+      is  => 'ro',
       isa => 'MyApp::User',
   );
 
@@ -101,7 +129,7 @@ assumes that any unknown type name passed as the C<isa> value for an
 attribute is a class. So this works:
 
   has 'birth_date' => (
-      is  => 'rw',
+      is  => 'ro',
       isa => 'DateTime',
   );
 
@@ -123,13 +151,13 @@ instances.
 
 =head1 SUBTYPES
 
-Moose uses subtypes in its built-in hierarchy. C<Int> is a child of
-C<Num> for example.
+Moose uses subtypes in its built-in hierarchy. For example, C<Int> is
+a child of C<Num>.
 
 A subtype is defined in terms of a parent type and a constraint. Any
-constraints defined by the parent(s) will be checked first, and then
-the the subtype's. A value must pass I<all> of these checks to be
-valid for the subtype.
+constraints defined by the parent(s) will be checked first, followed by
+constraints defined by the subtype. A value must pass I<all> of these
+checks to be valid for the subtype.
 
 Typically, a subtype takes the parent's constraint and makes it more
 specific.
@@ -138,33 +166,20 @@ A subtype can also define its own constraint failure message. This
 lets you do things like have an error "The value you provided (20),
 was not a valid rating, which must be a number from 1-10." This is
 much friendlier than the default error, which just says that the value
-failed a validation check for the type.
+failed a validation check for the type. The default error can, however,
+be made more friendly by installing L<Devel::PartialDump> (version 0.14 or
+higher), which Moose will use if possible to display the invalid value.
 
 Here's a simple (and useful) subtype example:
 
-  subtype 'PositiveInt'
-      => as 'Int'
-      => where { $_ > 0 }
-      => message { "The number you provided, $_, was not a positive number" }
+  subtype 'PositiveInt',
+      as 'Int',
+      where { $_ > 0 },
+      message { "The number you provided, $_, was not a positive number" };
 
 Note that the sugar functions for working with types are all exported
 by L<Moose::Util::TypeConstraints>.
 
-=head2 Creating a new type (that isn't a subtype)
-
-You can also create new top-level types:
-
-  type 'FourCharacters' => where { defined $_ && length $_ == 4 };
-
-In practice, this example is more or less the same as subtyping
-C<Str>, except you have to check definedness yourself.
-
-It's hard to find a case where you wouldn't want to subtype a very
-broad type like C<Defined>, C<Ref> or C<Object>.
-
-Defining a new top-level type is conceptually the same as subtyping
-C<Item>.
-
 =head1 TYPE NAMES
 
 Type names are global throughout the current Perl
@@ -177,42 +192,51 @@ you prefix names with some sort of namespace indicator to prevent
 these sorts of collisions.
 
 For example, instead of calling a type "PositiveInt", call it
-"MyApp.Type.PositiveInt".
+"MyApp::Type::PositiveInt" or "MyApp::Types::PositiveInt". We
+recommend that you centralize all of these definitions in a single
+package, C<MyApp::Types>, which can be loaded by other classes in your
+application.
+
+However, before you do this, you should look at the L<MooseX::Types>
+module. This module makes it easy to create a "type library" module, which can
+export your types as perl constants.
+
+  has 'counter' => (is => 'rw', isa => PositiveInt);
 
-Type names are just strings. We recommend that you I<do not> use "::"
-as a separator in type names. This can be very confusing, because
-class names are I<also> valid type names! Using something else, like a
-period, makes it clear that "MyApp::User" is a class and
-"MyApp.Type.PositiveInt" is a Moose type defined by your application.
+This lets you use a short name rather than needing to fully qualify the name
+everywhere. It also allows you to easily create parameterized types:
 
-The L<MooseX::Types> module lets you create bareword aliases to longer
-names and also automatically namespaces all the types you define.
+  has 'counts' => (is => 'ro', isa => HashRef[PositiveInt]);
+
+This module will check your names at compile time, and is generally more
+robust than the string type parsing for complex cases.
 
 =head1 COERCION
 
-One of the most powerful features of Moose's type system is its
-coercions. A coercion is a way to convert from one type to another.
+A coercion lets you tell Moose to automatically convert one type to another.
+
+  subtype 'ArrayRefOfInts',
+      as 'ArrayRef[Int]';
 
-  subtype 'ArrayRefOfInts'
-      => as 'ArrayRef[Int]';
+  coerce 'ArrayRefOfInts',
+      from 'Int',
+      via { [ $_ ] };
 
-  coerce 'ArrayRefOfInts'
-      => from 'Int'
-      => via { [ $_ ] };
+You'll note that we created a subtype rather than coercing C<ArrayRef[Int]>
+directly. It's a bad idea to add coercions to the raw built in
+types.
 
-You'll note that we had to create a subtype rather than coercing
-C<ArrayRef[Int]> directly. This is just a quirk of how Moose
-works.
+Coercions are global, just like type names, so a coercion applied to a built
+in type is seen by all modules using Moose types. This is I<another> reason
+why it is good to namespace your types.
 
-Coercions, like type names, are global. This is I<another> reason why
-it is good to namespace your types. Moose will I<never> try to coerce
-a value unless you explicitly ask for it. This is done by setting the
-C<coerce> attribute parameter to a true value:
+Moose will I<never> try to coerce a value unless you explicitly ask for
+it. This is done by setting the C<coerce> attribute option to a true value:
 
   package Foo;
 
   has 'sizes' => (
-      is     => 'rw',
+      is     => 'ro',
       isa    => 'ArrayRefOfInts',
       coerce => 1,
   );
@@ -227,16 +251,16 @@ object will have C<[ 42 ]> as its C<sizes> attribute.
 Deep coercion is the coercion of type parameters for parameterized
 types. Let's take these types as an example:
 
-  subtype 'HexNum'
-      => as 'Str'
-      => where { /[a-f0-9]/i };
+  subtype 'HexNum',
+      as 'Str',
+      where { /[a-f0-9]/i };
 
-  coerce 'Int'
-      => from 'HexNum'
-      => via { hex $_ };
+  coerce 'Int',
+      from 'HexNum',
+      via { hex $_ };
 
   has 'sizes' => (
-      is     => 'rw',
+      is     => 'ro',
       isa    => 'ArrayRef[Int]',
       coerce => 1,
   );
@@ -247,27 +271,27 @@ attribute, Moose will not do any coercion.
 However, you can define a set of subtypes to enable coercion between
 two parameterized types.
 
-  subtype 'ArrayRefOfHexNums'
-      => as 'ArrayRef[HexNum]';
+  subtype 'ArrayRefOfHexNums',
+      as 'ArrayRef[HexNum]';
 
-  subtype 'ArrayRefOfInts'
-      => as 'ArrayRef[Int]';
+  subtype 'ArrayRefOfInts',
+      as 'ArrayRef[Int]';
 
-  coerce 'ArrayRefOfInts'
-      => from 'ArrayRefOfHexNums'
-      => via { [ map { hex } @{$_} ] };
+  coerce 'ArrayRefOfInts',
+      from 'ArrayRefOfHexNums',
+      via { [ map { hex } @{$_} ] };
 
   Foo->new( sizes => [ 'a1', 'ff', '22' ] );
 
 Now Moose will coerce the hex numbers to integers.
 
-However, Moose does not attempt to chain coercions, so it will not
+Moose does not attempt to chain coercions, so it will not
 coerce a single hex number. To do that, we need to define a separate
 coercion:
 
-  coerce 'ArrayRefOfInts'
-      => from 'HexNum'
-      => via { [ hex $_ ] };
+  coerce 'ArrayRefOfInts',
+      from 'HexNum',
+      via { [ hex $_ ] };
 
 Yes, this can all get verbose, but coercion is tricky magic, and we
 think it's best to make it explicit.
@@ -294,9 +318,7 @@ coercion might be a better answer.
 For our example above, we might want to be more specific, and insist
 that output be an object with a C<print> method:
 
-  subtype 'CanPrint'
-      => as 'Object'
-      => where { $_->can('print') };
+  duck_type 'CanPrint', [qw(print)];
 
 We can coerce file handles to an object that satisfies this condition
 with a simple wrapper class:
@@ -306,7 +328,7 @@ with a simple wrapper class:
   use Moose;
 
   has 'handle' => (
-      is  => 'ro',
+      is  => 'rw',
       isa => 'FileHandle',
   );
 
@@ -314,7 +336,7 @@ with a simple wrapper class:
       my $self = shift;
       my $fh   = $self->handle();
 
-      print $fh @_;
+      print {$fh} @_;
   }
 
 Now we can define a coercion from C<FileHandle> to our wrapper class:
@@ -336,25 +358,25 @@ make your class internals simpler.
 
 The L<Moose::Util::TypeConstraints> module exports a number of helper
 functions for creating specific kinds of types. These include
-C<class_type>, C<role_type>, and C<maybe_type>. See the docs for
-details.
+C<class_type>, C<role_type>, C<maybe_type>, and C<duck_type>. See the
+docs for details.
 
 One helper worth noting is C<enum>, which allows you to create a
 subtype of C<Str> that only allows the specified values:
 
-  enum 'RGB' => qw( red green blue );
+  enum 'RGB', [qw( red green blue )];
 
-This creates a type named C<RGB>
+This creates a type named C<RGB>.
 
 =head1 ANONYMOUS TYPES
 
 All of the type creation functions return a type object. This type
 object can be used wherever you would use a type name, as a parent
-type, or as the value for an attribute's C<isa> parameter:
+type, or as the value for an attribute's C<isa> option:
 
   has 'size' => (
-      is => 'rw',
-      isa => subtype 'Int' => where { $_ > 0 },
+      is  => 'ro',
+      isa => subtype( 'Int' => where { $_ > 0 } ),
   );
 
 This is handy when you want to create a one-off type and don't want to
@@ -388,7 +410,7 @@ parameter validation using Moose types, including
 L<MooseX::Method::Signatures>, which gives you a full-blown C<method>
 keyword.
 
-  method morning (Str $name) {
+  method morning ( Str $name ) {
       $self->say("Good morning ${name}!");
   }
 
@@ -398,32 +420,8 @@ Because Moose types are defined at runtime, you may run into load
 order problems. In particular, you may want to use a class's type
 constraint before that type has been defined.
 
-We have several recommendations for ameliorating this problem. First,
-define I<all> of your custom types in one module,
-C<MyApp::Types>. Second, load this module in all of your other
-modules.
-
-If you are still having load order problems, you can make use of the
-C<find_type_constraint> function exported by
-L<Moose::Util::TypeConstraints>:
-
-  class_type('MyApp::User')
-      unless find_type_constraint('MyApp::User') || ;
-
-This sort of "find or create" logic is simple to write, and will let
-you work around load order issues.
-
-=head1 AUTHOR
-
-Dave Rolsky E<lt>autarch@urth.orgE<gt>
-
-=head1 COPYRIGHT AND LICENSE
-
-Copyright 2009 by Infinity Interactive, Inc.
-
-L<http://www.iinteractive.com>
-
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
+In order to ameliorate this problem, we recommend defining I<all> of your
+custom types in one module, C<MyApp::Types>, and then loading this module in
+all of your other modules.
 
 =cut