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
+example, a C<Num> is anything that Perl thinks looks like a number, an
C<Object> is a blessed reference, etc.
The types followed by "[`a]" can be parameterized. So instead of just
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>.
Now you can use C<'MyApp::User'> as a type name:
has creator => (
- is => 'rw',
+ is => 'ro',
isa => 'MyApp::User',
);
attribute is a class. So this works:
has 'birth_date' => (
- is => 'rw',
+ is => 'ro',
isa => 'DateTime',
);
=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.
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.
+
+Once you're doing this, you should almost certainly look at the
+L<MooseX::Types> extension which allows easy declaration of type libraries
+and can export your types as perl constants so that you can refer to them
+as just
+
+ 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.
+rather than needing to fully qualify them everywhere. It also allows
-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]);
+
+and similarly for the union and other syntax discussed below, which
+will compile time check your use of names and is generally more robust
+than the string type parsing for complex cases.
=head1 COERCION
package Foo;
has 'sizes' => (
- is => 'rw',
+ is => 'ro',
isa => 'ArrayRefOfInts',
coerce => 1,
);
=> via { hex $_ };
has 'sizes' => (
- is => 'rw',
+ is => 'ro',
isa => 'ArrayRef[Int]',
coerce => 1,
);
use Moose;
has 'handle' => (
- is => 'ro',
+ is => 'rw',
isa => 'FileHandle',
);
enum 'RGB' => qw( red green blue );
-This creates a type named C<RGB>
+This creates a type named C<RGB>.
=head1 ANONYMOUS TYPES
type, or as the value for an attribute's C<isa> option:
has 'size' => (
- is => 'rw',
+ is => 'ro',
isa => subtype 'Int' => where { $_ > 0 },
);
L<Moose::Util::TypeConstraints>:
class_type('MyApp::User')
- unless find_type_constraint('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.