Почему «use overload» не работает с «use namespace: autoclean»? - PullRequest
12 голосов
/ 12 октября 2011

Хорошо, просто проверка работоспособности не работает для меня.Я не знаю, какая у меня версия perl, или версия overload.pm, или что-то не так с тем, как я это реализовал, но этот код не работает для меня.

версия perl

This is perl, v5.10.1 (*) built for x86_64-linux-gnu-thread-multi

версия с перегрузкой

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;

отпечатки

 $VAR1 = 12900840;

Хуже всего то, что я не получаю никаких предупреждений или ошибок в журнале.

ОБНОВЛЕНИЕ

Спасибо Фрайдо за обнаружение проблемы.Я обновил вопрос на тот случай, если кто-нибудь еще наткнется на это.

Разве сообщество Perl / Moose обычно не использует перегрузку?

Ответы [ 3 ]

16 голосов
/ 12 октября 2011

namespace::autoclean наполняется магией, которую overload добавляет, чтобы справиться с вашим оператором. Следующие работы, как и следовало ожидать:

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;

Случайный взгляд не обнаруживает ничего в namespace::autoclean документах, касающихся этого, так что я думаю, что это непредвиденная особенность. Некоторые поиски показывают, что ошибка была зарегистрирована.

Я полагаю, это сводится к специальным символам, которые overload добавляет в ваш пакет. Перегрузка + добавляет записи таблицы символов (), (+ и OVERLOAD. Я предполагаю, что некоторые или все из них очищены пылесосом на namespace::autoclean, что устраняет вашу перегрузку.

Если вы любите приключения, вот патч для namespace::autoclean, отфильтровывающий символы перегрузки.

10 голосов
/ 12 октября 2011

Так что фридо абсолютно правильно; проблема заключается в эвристическом классе, который :: MOP использует для определения того, что является, а что не является «методом». Как правило, все, что импортируется из другого пакета, не является методом, и перегрузки технически квалифицируются как таковые. Поскольку namespace :: autoclean спрашивает Class :: MOP, какие методы существуют для пакета и удаляет остальные, autoclean вслепую удаляет перегрузки вместе со всем остальным.

Что довольно удивительно, я думаю.

MooseX :: MarkAsMethods поможет с этим для классов Moose; он запускается раньше, чем autoclean, и говорит Moose распознавать любые символы кода перегрузки для этого пакета как методы. Это избавляет их от топора autoclean и дает дополнительное преимущество, заключающееся в том, что теперь вы можете использовать перегрузки в ролях, использовать их и заставлять их «просто работать». (Полное раскрытие: я написал MX :: MarkAsMethods после того, как мое автоочистка была отклонена 2 года назад.)

Однако это не помогает с классами не-Moose, с которыми вы можете использовать autoclean ... Удаление перегрузок с помощью autoclean, в лучшем случае, является недостатком autoclean.

0 голосов
/ 20 апреля 2012

У меня была такая же проблема (в моем случае была попытка перегрузить ""), но MooseX :: MarkAsMethods еще не работал. Пока не выяснил почему, но альтернативное исправление, которое сделал - это использование MooseX :: Role :: WithOverloading (и, поскольку я уже использовал различные роли, он легко подходил).

package MyClass;
use Moose;
use namespace::autoclean;
with 'MyRole';

package MyRole;
use MooseX::Role::WithOverloading;

use overload '""' => sub { ... };
...