Commits

Toby Inkster committed 38b14f6

improved documentation; export constants; etc

  • Participants
  • Parent commits d50d5cb

Comments (0)

Files changed (2)

File lib/Scalar/Does.pm

 use strict;
 use utf8;
 
+our %_CONSTANTS;
 BEGIN {
 	$Scalar::Does::AUTHORITY = 'cpan:TOBYINK';
-	$Scalar::Does::VERSION   = '0.001';
+	$Scalar::Does::VERSION   = '0.002';
+	
+	%_CONSTANTS = (
+		BOOLEAN    => q[bool],
+		STRING     => q[""],
+		NUMBER     => q[0+],
+		REGEXP     => q[qr],
+		SMARTMATCH => q[~~],
+		map {; $_ => $_ } qw(
+			SCALAR ARRAY HASH CODE REF GLOB
+			LVALUE FORMAT IO VSTRING
+		)
+	);
 }
 
+use constant \%_CONSTANTS;
 use overload ();
-#	q[~~]    => sub { shift->(@_) },
-#	fallback => 1;
-
 use Carp             0     qw( confess );
 use IO::Detect       0.001 qw( is_filehandle );
 use namespace::clean 0.19  qw();
-use Scalar::Util     1.20  qw( blessed reftype );
+use Scalar::Util     1.20  qw( blessed reftype looks_like_number );
 
 use Sub::Exporter -setup => {
 	exports => [
-		qw( does overloads blessed reftype ),
+		qw( does overloads blessed reftype looks_like_number ),
 		custom => \&_build_custom,
+		keys %_CONSTANTS,
 	],
 	groups  => {
-		default => [qw( does )],
+		default        => [qw( does )],
+		constants      => [qw( -default -only_constants )],
+		only_constants => [keys %_CONSTANTS],
 	},
 	installer => sub {
 		namespace::clean->import(
 	if (my $test = $ROLES{$role})
 	{
 		local $_ = $thing;
-		my $does = $test->($thing);
-		return 1 if $does;
-	}
-	
-	if (blessed $thing)
-	{
-		return 1 if $thing->DOES($role);
+		return !! $test->($thing);
 	}
 	
 	if (blessed $role and $role->can('check'))
 	{
-		return 1 if $role->check($thing);
+		return !! $role->check($thing);
+	}
+	
+	if (blessed $thing && $thing->can('DOES'))
+	{
+		return 1 if $thing->DOES($role);
+	}
+	elsif (UNIVERSAL::can($thing, 'can') && $thing->can('DOES'))
+	{
+		my $class = $thing;
+		return '0E0' if $class->DOES($role);
 	}
 	
 	return;
 
 Checks if the scalar can be used as a scalar reference.
 
+Note: this role does not check whether a scalar is a scalar (which is
+obviously true) but whether it is a reference to another scalar.
+
 =item * B<ARRAY> or B<< @{} >>
 
 Checks if the scalar can be used as an array reference.
 Checks if the scalar can be used as a number. (It's pretty rare for this
 to not be true.)
 
+Note that this is far looser than C<looks_like_number> from L<Scalar::Util>.
+For example, an unblessed arrayref can be used as a number (it numifies to
+its reference address); the string "Hello World" can be used as a number (it
+numifies to 0).
+
 =item * B<< ~~ >>
 
 Checks if the scalar can be used on the right hand side of a smart match.
 
 =back
 
-For roles not on the predefined list above, the following behaviour is
-followed:
+If the given I<role> is blessed, and provides a C<check> method, then
+C<< does >> delegates to that.
 
-=over
+Otherwise, if the scalar being tested is blessed, then
+C<< $scalar->DOES($role) >> is called, and C<does> returns true if
+the method call returned true.
 
-=item 1. If the given scalar is blessed, then C<< $scalar->DOES($role) >>
-is called, and if that returns true, then C<< does >> returns true.
+If the scalar being tested looks like a Perl class name, then 
+C<< $scalar->DOES($role) >> is also called, and the string "0E0" is
+returned, which evaluates to 0 in a numeric context but true in a
+boolean context. This is an experimental feature; it has not yet
+been decided whether true or false is the correct response.
 
-=item 2. If the given I<role> is blessed, and provides a C<check> method,
-then C<< does >> delegates to that. This allows L<MooseX::Types> types to
-be used as roles. (But not L<Moose>'s type constraint strings.)
-
-=back
+Note that the C<DOES> method is only defined in L<UNIVERSAL> in
+Perl 5.10+. You may wish to load L<UNIVERSAL::DOES> on earlier versions
+of Perl.
 
 =item C<< overloads($scalar, $role) >>
 
 A function C<overloads> (which just checks overloading) is also available.
 
-=item C<< blessed($scalar) >>, C<< reftype($scalar) >>
+=item C<< blessed($scalar) >>, C<< reftype($scalar) >>, C<< looks_like_number($scalar) >>
 
 For convenience, this module can also re-export these functions from
-L<Scalar::Util>.
+L<Scalar::Util>. C<looks_like_number> is generally more useful than
+C<< does($scalar, q[0+]) >>.
+
+=back
+
+=head2 Constants
+
+The following constants may be used for convenience:
+
+=over
+
+=item C<SCALAR>
+
+=item C<ARRAY>
+
+=item C<HASH>
+
+=item C<CODE>
+
+=item C<GLOB>
+
+=item C<REF>
+
+=item C<LVALUE>
+
+=item C<IO>
+
+=item C<VSTRING>
+
+=item C<FORMAT>
+
+=item C<REGEXP>
+
+=item C<BOOLEAN>
+
+=item C<STRING>
+
+=item C<NUMBER>
+
+=item C<SMARTMATCH>
 
 =back
 
 L<Moose::Object> provides a C<does> method, and you should be able to use
 Scalar::Does without interfering with that.
 
+You can import the constants (plus C<does>) using:
+
+  use Scalar::Does -constants;
+
+Or list specific functions/constants that you wish to import:
+
+  use Scalar::Does qw( does ARRAY HASH STRING NUMBER );
+
 =head2 Custom Role Checks
 
   use Scalar::Does
 
 =head1 SEE ALSO
 
-L<Scalar::Util>, L<Moose::Role>, L<MooseX::Types>.
+L<Scalar::Util>.
 
 L<http://perldoc.perl.org/5.10.0/perltodo.html#A-does()-built-in>.
 
+=head2 Relationship to Moose roles
+
+Scalar::Does is not dependent on Moose, and its role-checking is not specific
+to Moose's idea of roles, but it does work well with Moose roles.
+
+Moose::Object overrides C<DOES>, so Moose objects and Moose roles should
+"just work" with Scalar::Does.
+
+  {
+    package Transport;
+    use Moose::Role;
+  }
+  
+  {
+    package Train;
+    use Moose;
+    with qw(Transport);
+  }
+  
+  my $thomas = Train->new;
+  does($thomas, 'Train');          # true
+  does($thomas, 'Transport');      # true
+  does($thomas, Transport->meta);  # not yet supported!
+
+L<Mouse::Object> should be compatible enough to work as well, but seemingly
+not L<Moo::Object>.
+
+See also:
+L<Moose::Role>,
+L<Moose::Object>,
+L<UNIVERSAL>.
+
+=head2 Relationship to Moose type constraints
+
+L<Moose::Meta::TypeConstraint> objects, plus the constants exported by
+L<MooseX::Types> libraries all provide a C<check> method, so again, should
+"just work" with Scalar::Does. Type constraint strings are not supported
+however.
+
+  use Moose::Util::TypeConstraints qw(find_type_constraint);
+  use MooseX::Types qw(Int);
+  use Scalar::Does qw(does);
+  
+  my $int = find_type_constraint("Int");
+  
+  does( "123", $int );     # true
+  does( "123", Int );      # true
+  does( "123", "Int" );    # false
+
+L<Mouse::Meta::TypeConstraints> and L<MouseX::Types> should be compatible
+enough to work as well.
+
+See also:
+L<Moose::Meta::TypeConstraint>,
+L<Moose::Util::TypeConstraints>,
+L<MooseX::Types>.
+
+=head2 Relationship to Object::DOES
+
+L<Object::DOES> provides a convenient way of overriding C<DOES> in your
+classes.
+
+  {
+    package Train;
+    use Object::DOES -role => [qw/ Transport /];
+    sub new { my ($class, %arg) = @_; bless \%arg, $class }
+  }
+  
+  my $thomas = Train->new;
+  does($thomas, 'Train');      # true
+  does($thomas, 'Transport');  # true
+
+See also:
+L<Object::DOES>.
+
 =head1 AUTHOR
 
 Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

File meta/changes.pret

 	issued  2012-09-02;
 	label   "Initial release".
 
+`Scalar-Does 0.002 cpan:TOBYINK`
+	issued  2012-09-19;
+	changeset [
+		item "Export constants for pre-defined roles."^^Addition;
+		item "Better documentation for interaction with Moose roles and type constraints."^^Documentation;
+		item "Document relationship with Object::DOES."^^Documentation;
+		item "Minor improvements."^^Documentation;
+		item "Export looks_like_number."^^Addition;
+		item "Clarify that does($thing, '0+') is not the same as looks_like_number."^^Documentation;
+	].