package ChainComparable; use strict; use UNIVERSAL (); sub new { my $class = shift; # allow for returning either a list or a scalar return wantarray ? (map { my $i = $_; bless \$i, $class } @_) : (bless \shift, $class); } sub comparison { # whee, currying my $sub = shift; return sub { my ($a, $b, $swap) = @_; $a = $$a; # allow for comparisons between two instances of this class $b = $$b if UNIVERSAL::isa($b, __PACKAGE__); # put the args in the right order ($a, $b) = ($b, $a) if $swap; if (defined $a and $sub->($a, $b)) { if ($b != 0) { return __PACKAGE__->new($b) } else { return __PACKAGE__->new("0 but true") } } else { return __PACKAGE__->new(undef) } }; } use overload ( bool => sub { $$_[0] }, '""' => sub { $$_[0] }, "0+" => sub { $$_[0] }, "==" => comparison(sub { $_[0] == $_[1] }), "!=" => comparison(sub { $_[0] != $_[1] }), "<<" => comparison(sub { $_[0] < $_[1] }), ">>" => comparison(sub { $_[0] > $_[1] }), );