2011-10-12 85 views
12

只是爲了理智檢查超載似乎沒有爲我工作。我不知道它是我擁有的perl版本還是overload.pm的版本,或者是我已經實現它的錯誤,但是這段代碼不適用於我。爲什麼「use overload」與「use namespace:autoclean」一起工作?

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

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

感謝Freido尋找問題。我已經更新了這個問題,以防其他人絆倒在這。

Perl/Moose社區通常不使用超載嗎?

回答

16

namespace::autocleanoverload增加處理您的操作員添加的魔法相媲美。正如你所期望的以下工作:

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真空,從而消除你的超載。

如果你覺得冒險,here's a patchnamespace::autoclean,它會過濾掉過載符號。

+1

+1找到解決方案後,我在桌子上敲了我的頭一兩個小時試圖找到我的代碼問題。愚蠢的圖書館錯誤! – qodeninja

+1

在那裏,做到了。 :)我對你的問題感到非常困惑,直到我記得'overload'通過插入魔法符號工作,我想知道'autoclean'是否搞亂了它們。 – friedo

+3

@nodebunny,當你可以自己寫自己的時候,爲什麼會抱怨別人的代碼? :)這個問題啓發了我寫[namespace :: sweep](http://search.cpan.org/~friedo/namespace-sweep/lib/namespace/sweep.pm),它不會踐踏你的重載。更多信息[這裏](http://blogs.perl.org/users/mike_friedman/2011/10/announcing-namespacesweep.html)。 – friedo

10

所以friedo是絕對正確的;問題在於啓發式Class :: MOP用來確定什麼是和什麼不是「方法」。一般來說,從另一個軟件包導入的任何內容都不是一種方法,並且在技術上超載的限制就是這樣。由於namespace :: autoclean向Class :: MOP請求包中存在哪些方法並刪除了其餘部分,autoclean會盲目地清除重載以及其他所有內容。

我覺得這很令人驚訝。

MooseX::MarkAsMethods將幫助這個穆斯類;它在autoclean之前運行並告訴Moose將該程序包的任何重載代碼符號識別爲方法。這讓他們擺脫了autoclean的斧頭,並且具有額外的優勢,現在你可以在角色中使用重載,消耗它們,讓它們「只是工作」。 (完全公開:我的autoclean修復在2年前被拒絕後,我寫了MX :: MarkAsMethods。)

但是,這並不能幫助您使用autoclean的非Moose類...... autoclean去除重載是autoclean中的一個缺陷。

+5

'缺陷'太實際了,'namespace :: autoclean'因爲這個而被破壞。你的修復是完美的順便說一句,這是一個恥辱的維護者是固執的。 –

0

我有同樣的問題(試圖超載""在我的情況),但還沒有MooseX :: MarkAsMethods工作。沒有考慮到爲什麼正確,但工作的替代修復是使用MooseX::Role::WithOverloading(並且因爲我已經在使用它很容易安裝的各種角色)。

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

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

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