=head1 NAME

MooseX::Types::NumUnit - Type(s) for using units in Moose

=head1 SYNOPSIS

 package MyPackage

 use Moose;
 use MooseX::Types::NumUnit qw/NumUnit NumSI num_of_unit/;

 has 'quantity' => ( isa => NumUnit, default => 0 );
 has 'si_quantity' => ( isa => NumSI, required => 1 );
 has 'length' => ( isa => num_of_unit('m'), default => '1 ft' );

=head1 DESCRIPTION

This module provides types (C<NumUnit> and friends) for Moose which represent physical units. More accurately it provides String to Number coercions, so that even if the user inputs a number with an incorrect (but compatible) unit, it will automatically coerce to a number of the correct unit.

A few things to note: since C<NumUnit> and friends are subtypes of C<Num>, a purely numerical value will not be coerced. This is by design, but should be kept in mind. Also C<NumUnit> and friends are coerced by default (see L</AUTOMATIC COERCION>).

=head1 PACKAGE VARIABLES

=head2 C<$MooseX::Types::NumUnit::Verbose>

When set to a true value, a string representing any conversion will be printed to C<STDERR> during coercion.

=head1 TYPE-LIKE FUNCTIONS

Since version 0.02, C<MooseX::Types::NumUnit> does not provide global types. Rather it has exportable type-like function which behave like types but do not pollute the "type namespace". While they behave like types, remember they are functions and they should not be quoted when called. They are null prototyped though, should they shouldn't (usually) need parenthesis. Futher they are not exported by default and must be requested. For more information about this system see L<MooseX::Types>.

=head2 C<NumUnit>

A subtype of C<Num> which accepts a number with a unit, but discards the unit on coercion to a C<Num>. This is the parent unit for all other units provided herein. Of course those have different coercions.

=head2 C<NumSI>

A subtype of C<NumUnit> which coerces to the SI equivalent of the unit passed in (i.e. a number in feet will be converted to a number in meters). In truth it is not strictly the SI equivalent, but whatever L<Physics::Unit> thinks is the base unit. This should always be SI (I hope!).

=head1 ANONYMOUS TYPE GENERATORS

This module provides functions which return anonymous types which satisfy certain criteria. These functions may be exported on request, but are not exported by default.

=head2 C<num_of_unit( $unit )>

Creates an anonymous type which has the given C<$unit>. If a number is passed in which can be converted to the specified unit, it is converted on coercion. If the number cannot be converted, the value of the attribute is set to C<0> and a warning is thrown.

=head2 C<num_of_si_unit_like( $unit )>

Creates an anonymous type which has the SI equivalent of the given C<$unit>. This is especially handy for composite units when you don't want to work out by hand what the SI base would be.

As a simple example, if C<$unit> is C<'ft'>, numbers passed in will be converted to meters! You see, the unit only helps specify the type of unit, however the SI unit is used. Another way to think of these types is as a resticted C<NumSI> of a certian quantity, allowing a loose specification.

As with C<num_of_unit>, if a number is passed in which can be converted to the specified (SI) unit, it is converted on coercion. If the number cannot be converted, the value of the attribute is set to C<0> and a warning is thrown.

=head1 AUTOMATIC COERCION

Since the NumUnit types provided by this module are essentially just C<Num> types with special coercions, it doesn't make sense to use them without coercions enabled on the attribute. To that end, this module mimics L<MooseX::AlwaysCoerce>, with the exception that it only enables coercion on C<NumUnit> and its subtypes. To prevent this, manually set C<< coerce => 0 >> for a given attribute and it will be left alone, or better yet, just use C<Num> as the type.

=head1 NOTES

This module defines the unit C<mm> (C<millimeter>) which L<Physics::Unit> inexplicably lacks. Also the author is investigating if C<nm> can be changed to C<nanometer> from C<nautical mile>, but so far this has not happened.

=head1 SEE ALSO

=over 4

=item L<Physics::Unit>

=item L<Math::Units::PhysicalValue>

=item L<MooseX::AlwaysCoerce>

=item L<MooseX::Types>

=back

=head1 SOURCE REPOSITORY

L<http://github.com/jberger/MooseX-Types-NumUnit>

=head1 AUTHOR

Joel Berger, E<lt>joel.a.berger@gmail.comE<gt>

=head1 COPYRIGHT AND LICENSE

Copyright (C) 2012 by Joel Berger

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.

