Подтвердить что ты не робот

Почему "использование перегрузки" не работает с "use namespace: autoclean"?

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

perl version

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);
  }

Основной

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;

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

UPDATE

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

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

4b9b3361

Ответ 1

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, которые обращаются к этому, поэтому я предполагаю, что это непредвиденная функция. Некоторые поиски показывают, что был сообщен bug.

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

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

Ответ 2

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

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

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

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

Ответ 3

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

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

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

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