Why doesn't “use overload” work with “use name

2019-04-19 23:29发布

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?

3条回答
干净又极端
2楼-- · 2019-04-19 23:41

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.

查看更多
时光不老,我们不散
3楼-- · 2019-04-19 23:49

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 { ... };
查看更多
姐就是有狂的资本
4楼-- · 2019-04-19 23:56

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.

查看更多
登录 后发表回答