Ok just to sanity check overload doesnt seem to be working for me. I don't know if it's the version of perl I have, or the version of overload.pm, or something wrong with how I've implemented it, but this code doesnt work for me.
perl version
This is perl, v5.10.1 (*) built for x86_64-linux-gnu-thread-multi
overload version
perl -Moverload -e 'print "$overload::VERSION\n";'
1.07
Token.pm
package Token;
use namespace::autoclean;
use Data::Dumper;
use Moose;
use Moose::Util::TypeConstraints;
use overload '+' => \&_overload_add, fallback => 1;
has 'secretvalue' => ( is => 'rw', isa => 'Int');
sub _overload_add{
my ( $one, $two ) = @_;
my $value = $one->secretvalue() + $two->secretvalue();
return ($value);
}
main
use strict;
use warnings;
use Token;
my $t = Token->new( secretvalue => 17, key => 'x' );
my $t2 = Token->new( secretvalue => 12, key => 'y' );
my $x = $t + $t2;
print $x;
prints
$VAR1 = 12900840;
The worst part is that I'm not getting any kind of warning or errors in the log.
UPDATE
Thanks to Freido for finding the problem. I've updated the question just in case anyone else stumbles on this.
Does the Perl/Moose community generally not use overload?
namespace::autoclean
is futzing with the magic that overload
adds to handle your operator. The following works as you would expect:
package Token;
use Moose;
use Moose::Util::TypeConstraints;
use overload '+' => '_overload_add';
has 'secretvalue' => ( is => 'rw', isa => 'Int');
sub _overload_add{
my ( $one, $two ) = @_;
my $value = $one->secretvalue() + $two->secretvalue();
return ($value);
}
1;
A casual glance does not reveal anything in the namespace::autoclean
docs that addresses this, so I guess it's an unanticipated feature. Some searching reveals that a bug has been reported.
I guess it comes down the special symbols that overload
adds to your package. Overloading +
adds the symbol table entries ()
, (+
, and OVERLOAD
. I'm guessing some or all of these are vacuumed up by namespace::autoclean
, thus undoing your overloading.
If you're feeling adventurous, here's a patch for namespace::autoclean
that filters out overload symbols.
So friedo is absolutely correct; the problem lies in the heuristic Class::MOP uses to determine what is and what isn't a "method". Generally, anything imported from another package is not a method, and overloads technically qualify as that. Since namespace::autoclean asks Class::MOP what methods exist for the package and removes the rest, autoclean blindly purges overloads along with everything else.
Which is pretty surprising, I think.
MooseX::MarkAsMethods will help with this for Moose classes; it runs before autoclean does and tells Moose to recognize any overload code symbols for that package as methods. This spares them autoclean's axe, and has the added advantage that now you can use overloads in roles, consume them, and have them "just work". (Full disclosure: I wrote MX::MarkAsMethods after my autoclean fix was rejected 2 years ago.)
However, this does not help with non-Moose classes you may want to use autoclean with... The removal of overloads by autoclean is, at best, a flaw in autoclean.
I've had the same problem (trying to overload ""
in my case), but haven't got MooseX::MarkAsMethods to work yet. Not looked into why properly yet, but an alternative fix that did work was to use MooseX::Role::WithOverloading (and since I already was using various roles it fitted easily).
package MyClass;
use Moose;
use namespace::autoclean;
with 'MyRole';
package MyRole;
use MooseX::Role::WithOverloading;
use overload '""' => sub { ... };