-
-
07 Nov 2021 03:41:58 UTC
- Distribution: Moose
- Source (raw)
- Browse (raw)
- Changes
- Homepage
- How to Contribute
- Repository
- Issues (71)
- Testers (2604 / 3 / 1)
- Kwalitee
Bus factor: 3- 92.11% Coverage
- License: perl_5
- Perl: v5.8.3
- Activity
24 month- Tools
- Download (881.54KB)
- MetaCPAN Explorer
- Permissions
- Subscribe to distribution
- Permalinks
- This version
- Latest version
and 142 contributors-
Stevan Little
-
Dave Rolsky
-
Jesse Luehrs
-
Shawn M Moore
-
יובל קוג'מן (Yuval Kogman)
-
Florian Ragwitz
-
Hans Dieter Pearcey
-
Chris Prather
-
Matt S Trout
-
Upasana Shukla
-
Graham Knop
-
Tomas Doran
-
Ricardo Signes
-
Guillermo Roditi
-
John Napiorkowski
-
Aankhen
-
Todd Hepler
-
Jonathan Rockway
-
Gerda Shank
-
Perlover
-
Shlomi Fish
-
Brad Bowman
-
Justin Hunter
-
Kent Fredric
-
Paul Driver
-
Anders Nor Berle
-
Brian Manning
-
gfx
-
Jay Hannah
-
Lars Dɪᴇᴄᴋᴏᴡ 迪拉斯
-
Leon Brocard
-
Olivier Mengué
-
Rafael Kitover
-
Christian Hansen
-
Cory Watson
-
Dagfinn Ilmari Mannsåker
-
Paul Jamieson Fenwick
-
Robert Buels
-
Dan Dascalescu
-
Marcel Grünauer
-
Scott McWhirter
-
Ævar Arnfjörð Bjarmason
-
Daisuke Maki (lestrrat)
-
Dylan William Hardison
-
Patrick Donelan
-
Stefan O'Rear
-
Tokuhiro Matsuno
-
Ash Berlin
-
Chris Weyl
-
Eric Wilhelm
-
Jess Robinson
-
Marc Mims
-
Marcus Ramberg
-
Mark Allen
-
Mateu X Hunter
-
matthof
-
Robert 'phaylon' Sedlacek
-
Zachary Lome
-
Aran Clary Deltac
-
Chip
-
Christopher J. Madsen
-
Curtis Jewell
-
Evan Carroll
-
Mark A. Stratman
-
Mark Fowler
-
Matthew Horsfall
-
mauke
-
Michael LaGrasta
-
Michael Rykov
-
Mike Whitaker
-
Moritz Onken
-
Nelo Onyiah
-
Nick Perez
-
Robert Boone
-
Robin V
-
rodrigolive
-
shelling
-
Thomas Sibley
-
Tom Hukins
-
Wallace Reis
-
Aaron Cohen
-
Adam J. Foxson
-
Adam Kennedy
-
Andy Jack
-
Anirvan Chatterjee
-
Ansgar Burchardt
-
A. Sinan Unur
-
Ben Hutton
-
Brendan Byrd
-
Chad Granum
-
Chankey Pathak
-
Chia-liang Kao
-
Christian Walde (Mithaldu)
-
chromatic
-
Dann
-
Dave Romano
-
David Leadbeater
-
David Steinbrunner
-
dmaestro
-
E. Choroba
-
franck cuny
-
Frew Schmidt
-
gregor herrmann
-
hakim
-
Henry Van Styn
-
James Marca
-
Jason May
-
Jay Allen
-
Jay Kuri
-
Jeff Bisbee
-
Jens Berthold
-
Jesse Vincent
-
joel
-
John Douglas Porter
-
John Goulah
-
Justin DeVuyst
-
Kang-min Liu
-
Leon Timmermans
-
Mark O Grady
-
Matt Kraai
-
Michael Schout
-
Nathan Gray
-
Olaf Alders
-
Olof Johansson
-
Paul Cochrane
-
Paweł Murias
-
Pedro Melo
-
Peter Shangov
-
Philippe Bruhat (BooK)
-
Philipp Gortan
-
Phillip Smith
-
Piotr Roszatycki
-
pktm
-
rouzier
-
Sam Vilain
-
sherrardb
-
Simon Reinhardt
-
sue spence
-
Tuomas Jormola
-
wickline
-
Yanick Champoux
-
Zoffix Znet
- Dependencies
- Carp
- Class::Load
- Class::Load::XS
- Data::OptList
- Devel::GlobalDestruction
- Devel::OverloadInfo
- Devel::StackTrace
- Dist::CheckConflicts
- Eval::Closure
- List::Util
- MRO::Compat
- Module::Runtime
- Module::Runtime::Conflicts
- Package::DeprecationManager
- Package::Stash
- Package::Stash::XS
- Params::Util
- Scalar::Util
- Sub::Exporter
- Sub::Util
- Try::Tiny
- parent
- strict
- warnings
- Reverse dependencies
- CPAN Testers List
- Dependency graph
- NAME
- VERSION
- TYPES IN PERL?
- THE TYPES
- WHAT IS A TYPE?
- SUBTYPES
- TYPE NAMES
- COERCION
- TYPE UNIONS
- TYPE CREATION HELPERS
- ANONYMOUS TYPES
- VALIDATING METHOD PARAMETERS
- LOAD ORDER ISSUES
- AUTHORS
- COPYRIGHT AND LICENSE
NAME
Moose::Manual::Types - Moose's type system
VERSION
version 2.2201
TYPES IN PERL?
Moose provides its own type system for attributes. You can also use 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 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.
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 type system makes it much easier to ensure that you are getting valid data, and it also contributes greatly to code maintainability.
THE TYPES
The basic Moose type hierarchy looks like this
Any 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
Any
andItem
is conceptual.Item
is used as the top-level type in the hierarchy.The rest of these types correspond to existing Perl concepts. In particular:
Bool
accepts1
for true, and undef, 0, or the empty string as false.Maybe[`a]
accepts either`a
orundef
.Num
accepts integers, floating point numbers (both in decimal notation & exponential notation), 0, .0, 0.0 etc. It doesn't accept numbers with whitespace, Inf, Infinity, "0 but true", NaN & other such strings.ClassName
andRoleName
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.FileHandle
accepts either an IO::Handle object or a builtin perl filehandle (see "openhandle" in Scalar::Util).Object
accepts any blessed reference.
The types followed by "[`a]" can be parameterized. So instead of just plain
ArrayRef
we can say that we wantArrayRef[Int]
instead. We can even do something likeHashRef[ArrayRef[Str]]
.The
Maybe[`a]
type deserves a special mention. Used by itself, it doesn't really mean anything (and is equivalent toItem
). When it is parameterized, it means that the value is eitherundef
or the parameterized type. SoMaybe[Int]
means an integer orundef
.For more details on the type hierarchy, see Moose::Util::TypeConstraints.
WHAT IS A TYPE?
It's important to realize that types are not classes (or packages). Types are just objects (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 appropriate object.However, class names can be type names. When you define a new class using Moose, it defines an associated type name behind the scenes:
package MyApp::User; use Moose;
Now you can use
'MyApp::User'
as a type name:has creator => ( is => 'ro', isa => 'MyApp::User', );
However, for non-Moose classes there's no magic. You may have to explicitly declare the class type. This is a bit muddled because Moose assumes that any unknown type name passed as the
isa
value for an attribute is a class. So this works:has 'birth_date' => ( is => 'ro', isa => 'DateTime', );
In general, when Moose is presented with an unknown name, it assumes that the name is a class:
subtype 'ModernDateTime' => as 'DateTime' => where { $_->year() >= 1980 } => message { 'The date you provided is not modern enough' }; has 'valid_dates' => ( is => 'ro', isa => 'ArrayRef[DateTime]', );
Moose will assume that
DateTime
is a class name in both of these instances.SUBTYPES
Moose uses subtypes in its built-in hierarchy. For example,
Int
is a child ofNum
.A subtype is defined in terms of a parent type and a constraint. Any constraints defined by the parent(s) will be checked first, followed by constraints defined by the subtype. A value must pass all of these checks to be valid for the subtype.
Typically, a subtype takes the parent's constraint and makes it more specific.
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. The default error can, however, be made more friendly by installing 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" };
Note that the sugar functions for working with types are all exported by Moose::Util::TypeConstraints.
TYPE NAMES
Type names are global throughout the current Perl interpreter. Internally, Moose maps names to type objects via a registry.
If you have multiple apps or libraries all using Moose in the same process, you could have problems with collisions. We recommend that 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" or "MyApp::Types::PositiveInt". We recommend that you centralize all of these definitions in a single package,
MyApp::Types
, which can be loaded by other classes in your application.However, before you do this, you should look at the 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);
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:
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.
COERCION
A coercion lets you tell Moose to automatically convert one type to another.
subtype 'ArrayRefOfInts', as 'ArrayRef[Int]'; coerce 'ArrayRefOfInts', from 'Int', via { [ $_ ] };
You'll note that we created a subtype rather than coercing
ArrayRef[Int]
directly. It's a bad idea to add coercions to the raw built in types.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 another reason why it is good to namespace your types.
Moose will never try to coerce a value unless you explicitly ask for it. This is done by setting the
coerce
attribute option to a true value:package Foo; has 'sizes' => ( is => 'ro', isa => 'ArrayRefOfInts', coerce => 1, ); Foo->new( sizes => 42 );
This code example will do the right thing, and the newly created object will have
[ 42 ]
as itssizes
attribute.Deep coercion
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 }; coerce 'Int', from 'HexNum', via { hex $_ }; has 'sizes' => ( is => 'ro', isa => 'ArrayRef[Int]', coerce => 1, );
If we try passing an array reference of hex numbers for the
sizes
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 'ArrayRefOfInts', as 'ArrayRef[Int]'; coerce 'ArrayRefOfInts', from 'ArrayRefOfHexNums', via { [ map { hex } @{$_} ] }; Foo->new( sizes => [ 'a1', 'ff', '22' ] );
Now Moose will coerce the hex numbers to integers.
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 $_ ] };
Yes, this can all get verbose, but coercion is tricky magic, and we think it's best to make it explicit.
TYPE UNIONS
Moose allows you to say that an attribute can be of two or more disparate types. For example, we might allow an
Object
orFileHandle
:has 'output' => ( is => 'rw', isa => 'Object | FileHandle', );
Moose actually parses that string and recognizes that you are creating a type union. The
output
attribute will accept any sort of object, as well as an unblessed file handle. It is up to you to do the right thing for each of them in your code.Whenever you use a type union, you should consider whether or not 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
print
method:duck_type 'CanPrint', [qw(print)];
We can coerce file handles to an object that satisfies this condition with a simple wrapper class:
package FHWrapper; use Moose; has 'handle' => ( is => 'rw', isa => 'FileHandle', ); sub print { my $self = shift; my $fh = $self->handle(); print {$fh} @_; }
Now we can define a coercion from
FileHandle
to our wrapper class:coerce 'CanPrint' => from 'FileHandle' => via { FHWrapper->new( handle => $_ ) }; has 'output' => ( is => 'rw', isa => 'CanPrint', coerce => 1, );
This pattern of using a coercion instead of a type union will help make your class internals simpler.
TYPE CREATION HELPERS
The Moose::Util::TypeConstraints module exports a number of helper functions for creating specific kinds of types. These include
class_type
,role_type
,maybe_type
, andduck_type
. See the docs for details.One helper worth noting is
enum
, which allows you to create a subtype ofStr
that only allows the specified values:enum 'RGB', [qw( red green blue )];
This creates a type named
RGB
.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
isa
option:has 'size' => ( is => 'ro', isa => subtype( 'Int' => where { $_ > 0 } ), );
This is handy when you want to create a one-off type and don't want to "pollute" the global namespace registry.
VALIDATING METHOD PARAMETERS
Moose does not provide any means of validating method parameters. However, there are several MooseX extensions on CPAN which let you do this.
The simplest and least sugary is Params::ValidationCompiler. This lets you validate a set of named parameters using Moose types:
use Moose::Util::TypeConstraints qw( find_type_constraint ); use Params::ValidationCompiler qw( validation_for ); { my $validator = validation_for( params => { foo => { type => find_type_constraint('Int') }, bar => { type => find_type_constraint('Str'), optional => 1, }, baz => { type => find_type_constraint('Int'), default => 42, }, }, ); sub foo { my %args = $validator->(@_); } }
Params::ValidationCompiler also supports coercions.
There are several more powerful extensions that support method parameter validation using Moose types, including Moops, which gives you a full-blown
method
keyword.method morning ( Str $name ) { $self->say("Good morning ${name}!"); }
LOAD ORDER ISSUES
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.
In order to ameliorate this problem, we recommend defining all of your custom types in one module,
MyApp::Types
, and then loading this module in all of your other modules.AUTHORS
Stevan Little <stevan@cpan.org>
Dave Rolsky <autarch@urth.org>
Jesse Luehrs <doy@cpan.org>
Shawn M Moore <sartak@cpan.org>
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
Karen Etheridge <ether@cpan.org>
Florian Ragwitz <rafl@debian.org>
Hans Dieter Pearcey <hdp@cpan.org>
Chris Prather <chris@prather.org>
Matt S Trout <mstrout@cpan.org>
COPYRIGHT AND LICENSE
This software is copyright (c) 2006 by Infinity Interactive, Inc.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
Module Install Instructions
To install Moose, copy and paste the appropriate command in to your terminal.
cpanm Moose
perl -MCPAN -e shell install Moose
For more information on module installation, please visit the detailed CPAN module installation guide.