Почему "использование перегрузки" не работает с "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 не использует перегрузку?
Ответы
Ответ 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 { ... };