File Coverage

blib/lib/Object/Boolean.pm
Criterion Covered Total %
statement 64 64 100.0
branch 16 18 88.8
condition 3 3 100.0
subroutine 24 24 100.0
pod 1 1 100.0
total 108 110 98.1


line stmt bran cond sub pod time code
1             package Object::Boolean;
2              
3 3     3   30779 use base 'Class::Data::Inheritable';
  3         6  
  3         3133  
4 3         1713 use Sub::Exporter -setup =>
5             { exports => { True => \&_build_true_or_false,
6 3     3   4369 False => \&_build_true_or_false } };
  3         52557  
7 3     3   1146 use warnings;
  3         17  
  3         81  
8 3     3   14 use strict;
  3         5  
  3         312  
9              
10             our $VERSION = '0.02';
11              
12             # overrideable class data
13             __PACKAGE__->mk_classdata( strTrue => 'true' );
14             __PACKAGE__->mk_classdata( strFalse => 'false' );
15             __PACKAGE__->mk_classdata( numTrue => 1 );
16             __PACKAGE__->mk_classdata( numFalse => 0 );
17              
18             # boolean behavior
19 3     3   17 use overload 'bool' => \&_is_true;
  3         4  
  3         31  
20              
21             # String behavior
22 3     3   195 use overload '""' => \&_str;
  3         11  
  3         15  
23 3     3   180 use overload 'eq' => \&_eq;
  3         4  
  3         14  
24 3     3   151 use overload 'ne' => \&_not_eq;
  3         4  
  3         13  
25 3     3   159 use overload 'not' => \&_not;
  3         7  
  3         14  
26              
27             # Numeric behavior
28 3     3   2148 use overload '0+' => \&_num;
  3         6  
  3         21  
29 3     3   178 use overload '==' => \&_num_eq;
  3         4  
  3         15  
30 3     3   191 use overload '!=' => \&_num_not_eq;
  3         5  
  3         15  
31 3     3   191 use overload '!' => \&_not;
  3         5  
  3         12  
32              
33             # constructor
34             sub new {
35 29     29 1 2843 my ( $class, $value ) = @_;
36 29 50       71 $class = ref $class if ref $class;
37 29 100 100     153 bless \(
38             my $state = ( !$value || $value eq $class->strFalse ? 0 : 1 )
39             ), $class;
40             }
41             # _is_true() and new() depend on $state being a scalar ref. Nothing else does.
42 87     87   3616 sub _is_true { my($s)=@_; $$s }
  87         375  
43              
44             # build exportable constants
45             sub _build_true_or_false {
46 4     4   531 my $class = shift;
47 4         5 my $name = shift;
48 4 50       13 my $method =
    100          
49             ( $name eq 'True' ? 'numTrue'
50             : $name eq 'False' ? 'numFalse'
51             : die("bad export param : $name") );
52 4     7   21 return sub { $class->new($class->$method) };
  7         494  
53             }
54              
55             # functions used in overloading
56 44 100   44   2989 sub _str { my($s)=@_; $s->_is_true ? $s->strTrue : $s->strFalse; }
  44         91  
57 14 100   14   194 sub _num { my($s)=@_; $s->_is_true ? $s->numTrue : $s->numFalse; }
  14         36  
58              
59 25 100   25   3337 sub _eq { my($s,$t)=@_; $s->_str eq (ref $t eq ref $s ? $t->_str : $t); }
  25         57  
60 8 100   8   1071 sub _num_eq { my($s,$t)=@_; $s->_num == (ref $t eq ref $s ? $t->_num : $t); }
  8         35  
61              
62 2     2   860 sub _not_eq { my($s,$t)=@_; !$s->_eq($t); }
  2         12  
63 2     2   813 sub _num_not_eq { my($s,$t)=@_; !$s->_num_eq($t);}
  2         12  
64              
65             sub _not {
66 7     7   1370 my ($s) = @_;
67 7         17 my $class = ref $s;
68 7 100       19 $s->_is_true ? $class->new( $class->numFalse ) : $class->new( $class->numTrue );
69             }
70              
71             =head1 NAME
72              
73             Object::Boolean - Represent boolean values as objects
74              
75             =head1 SYNOPSIS
76              
77             use Object::Boolean;
78             use Object::Boolean qw/True False/; # ..or export some constants
79             use Object::Boolean # ..or rename those constants
80             True => { -as => 'TRUE' },
81             False => { -as => 'FALSE' };
82              
83             # Create a "false" object by calling new() with a Perl
84             # false value or the word 'false'.
85             my $f = Object::Boolean->new(0);
86             my $f = Object::Boolean->new('');
87             my $f = Object::Boolean->new(2+2==3);
88             my $f = Object::Boolean->new('false');
89              
90             # Create a "true" object by calling new() with anything else
91             my $t = Object::Boolean->new(1);
92             my $t = Object::Boolean->new(2+2==4);
93             my $t = Object::Boolean->new('true');
94             my $t = Object::Boolean->new('elephant');
95              
96             # In boolean context, it behaves like a boolean value.
97             if ($f) { print "it's true" }
98             print "\$f is false" unless $f;
99             print "1+1==2 and it's true" if 1+1==2 && $t;
100              
101             # In string context, it becomes "true" or "false"
102             print "It was a $f alarm.";
103             print "Those are $f teeth.";
104              
105             # Boolean negation produces a new boolean object.
106             print (!$f)." love is hard to find.";
107              
108             # Checking for numeric or string equality with other boolean
109             # objects compares them as though they were in a boolean context.
110             if ($t!=$f) { print "They are not the same." } # like xor
111             if ($t==$t) { print "They are both true or both false." }
112             if (Object::Boolean->new(1) eq Object::Boolean->new(2)) {
113             # this will be true
114             }
115              
116             # Comparison to non-boolean objects treats booleans as strings
117             # for string equality or the numbers 0 or 1 for numeric equality
118             my $true = Object::Boolean->new('true');
119             print "true" if $true eq 'true'; # true
120             print 'true' if $true == 1; # also true
121             print 'true' if $true == 27; # no, not true
122             print 'true' if $true eq 'True'; # not true
123              
124             =head1 DESCRIPTION
125              
126             Package for representing booleans as objects which stringify to true/false
127             and numerify to 0/1. Derived classes can easily stringify/numerify to other
128             values.
129              
130             =head1 FUNCTIONS
131              
132             =over
133              
134             =item new
135              
136             Create a new Object::Boolean object.
137              
138             =back
139              
140             =head1 SEE ALSO
141              
142             Object::Boolean::YesNo -- to stringify to 'Yes' and 'No' instead of 'true' and 'false'.
143              
144             =head1 VERSION
145              
146             Version 0.02
147              
148             =head1 AUTHOR
149              
150             Brian Duggan, C<< >>
151              
152             =head1 LICENSE
153              
154             Copyright 2008 Brian Duggan, all rights reserved.
155              
156             This program is free software; you can redistribute it and/or modify it
157             under the same terms as Perl itself.
158              
159             =cut
160              
161             1;
162