Why doesn't "use overload" work with "use namespace:autoclean"?
Asked Answered
D

3

12

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?

Delphinus answered 12/10, 2011 at 3:18 Comment(0)
O
16

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.

Obfuscate answered 12/10, 2011 at 4:6 Comment(3)
+1 for finding solution after I pounded my head on the desk for an hour or two trying to find the problem with MY code. silly library bugs!Delphinus
Been there, done that. :) I was quite baffled by your problem too until I remembered that overload worked by inserting magic symbols, and I wondered if autoclean was messing with them.Obfuscate
@nodebunny, why complain about other people's code when you can write your own? :) This question inspired me to write namespace::sweep which will not trample your overloads. More info here.Obfuscate
E
10

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.

Endaendall answered 12/10, 2011 at 5:30 Comment(1)
flaw is being too kind, namespace::autoclean is flat out broken because of this. Your fix was perfect BTW, it is a shame the maintainer is being stubborn about it.Gingham
H
0

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 { ... };
Haymaker answered 20/4, 2012 at 10:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.