Make ->does, ->DOES safe on old perls (RT#100866)
[p5sagit/Safe-Isa.git] / lib / Safe / Isa.pm
CommitLineData
e6995dc6 1package Safe::Isa;
2
3use strict;
4use warnings FATAL => 'all';
5use Scalar::Util qw(blessed);
7b1885ee 6use Exporter 5.57 qw(import);
e6995dc6 7
d994d71c 8our $VERSION = '1.000005';
e6995dc6 9
10our @EXPORT = qw($_call_if_object $_isa $_can $_does $_DOES);
11
12our $_call_if_object = sub {
13 my ($obj, $method) = (shift, shift);
f3335392 14 # This is intentionally a truth test, not a defined test, otherwise
15 # we gratuitously break modules like Scalar::Defer, which would be
16 # un-perlish.
e6995dc6 17 return unless blessed($obj);
de8d80ef 18 return $obj->isa(@_) if lc($method) eq 'does' and not $obj->can($method);
e6995dc6 19 return $obj->$method(@_);
20};
21
22our ($_isa, $_can, $_does, $_DOES) = map {
23 my $method = $_;
24 sub { my $obj = shift; $obj->$_call_if_object($method => @_) }
25} qw(isa can does DOES);
26
b19500df 271;
28__END__
29
30=pod
31
e6995dc6 32=head1 NAME
33
34Safe::Isa - Call isa, can, does and DOES safely on things that may not be objects
35
36=head1 SYNOPSIS
37
38 use strict;
39 use warnings;
40
41 { package Foo; sub new { bless({}, $_[0]) } }
42 { package Bar; our @ISA = qw(Foo); sub bar { 1 } }
43
44 my $foo = Foo->new;
45 my $bar = Bar->new;
46 my $blam = [ 42 ];
47
48 # basic isa usage -
49
50 $foo->isa('Foo'); # true
51 $bar->isa('Foo'); # true
52 $blam->isa('Foo'); # BOOM
53
54 $foo->can('bar'); # false
55 $bar->can('bar'); # true
56 $blam->can('bar'); # BOOM
57
58 # Safe::Isa usage -
59
60 use Safe::Isa;
61
62 $foo->$_isa('Foo'); # true
63 $bar->$_isa('Foo'); # true
64 $blam->$_isa('Foo'); # false, no boom today
65
66 $foo->$_can('bar'); # false
67 $bar->$_can('bar'); # true
68 $blam->$_can('bar'); # false, no boom today
69
70Similarly:
71
72 $maybe_an_object->$_does('RoleName'); # true or false, no boom today
73 $maybe_an_object->$_DOES('RoleName'); # true or false, no boom today
74
75And just in case we missed a method:
76
77 $maybe_an_object->$_call_if_object(name => @args);
78
79Or to re-use a previous example for purposes of explication:
80
ff9518c5 81 $foo->$_call_if_object(isa => 'Foo'); # true
82 $bar->$_call_if_object(isa => 'Foo'); # true
83 $blam->$_call_if_object(isa => 'Foo'); # false, no boom today
e6995dc6 84
85=head1 DESCRIPTION
86
87How many times have you found yourself writing:
88
89 if ($obj->isa('Something')) {
90
91and then shortly afterwards cursing and changing it to:
92
93 if (Scalar::Util::blessed($obj) and $obj->isa('Something')) {
94
95Right. That's why this module exists.
96
97Since perl allows us to provide a subroutine reference or a method name to
98the -> operator when used as a method call, and a subroutine doesn't require
99the invocant to actually be an object, we can create safe versions of isa,
100can and friends by using a subroutine reference that only tries to call the
101method if it's used on an object. So:
102
103 my $isa_Foo = $maybe_an_object->$_call_if_object(isa => 'Foo');
104
105is equivalent to
106
107 my $isa_Foo = do {
108 if (Scalar::Util::blessed($maybe_an_object)) {
109 $maybe_an_object->isa('Foo');
110 } else {
111 undef;
112 }
113 };
114
fca38ff4 115Note that we don't handle trying class names, because many things are valid
116class names that you might not want to treat as one (like say "Matt") - the
117C<is_module_name> function from L<Module::Runtime> is a good way to check for
f94f3bbb 118something you might be able to call methods on if you want to do that.
fca38ff4 119
e6995dc6 120=head1 EXPORTS
121
122=head2 $_isa
123
124 $maybe_an_object->$_isa('Foo');
125
126If called on an object, calls C<isa> on it and returns the result, otherwise
127returns nothing.
128
129=head2 $_can
130
131 $maybe_an_object->$_can('Foo');
132
133If called on an object, calls C<can> on it and returns the result, otherwise
134returns nothing.
135
136=head2 $_does
137
138 $maybe_an_object->$_does('Foo');
139
140If called on an object, calls C<does> on it and returns the result, otherwise
141returns nothing.
142
143=head2 $_DOES
144
145 $maybe_an_object->$_DOES('Foo');
146
147If called on an object, calls C<DOES> on it and returns the result, otherwise
148returns nothing.
149
4703f64c 150=head2 $_call_if_object
e6995dc6 151
4703f64c 152 $maybe_an_object->$_call_if_object(method_name => @args);
e6995dc6 153
154If called on an object, calls C<method_name> on it and returns the result,
155otherwise returns nothing.
156
91dfd937 157=head1 SEE ALSO
158
159I gave a lightning talk on this module (and L<curry> and L<Import::Into>) at
160L<YAPC::NA 2013|https://www.youtube.com/watch?v=wFXWV2yY7gE&t=46m05s>.
161
e6995dc6 162=head1 AUTHOR
163
164mst - Matt S. Trout (cpan:MSTROUT) <mst@shadowcat.co.uk>
165
166=head1 CONTRIBUTORS
167
168None yet. Well volunteered? :)
169
170=head1 COPYRIGHT
171
172Copyright (c) 2012 the Safe::Isa L</AUTHOR> and L</CONTRIBUTORS>
173as listed above.
174
175=head1 LICENSE
176
177This library is free software and may be distributed under the same terms
178as perl itself.
179
180=cut