2011-10-12 5 views
12

Ok solo per la sanità mentale, il sovraccarico non sembra funzionare per me. Non so se è la versione di Perl che ho, o la versione di overload.pm, o qualcosa di sbagliato in come l'ho implementata, ma questo codice non funziona per me.Perché "use overload" non funziona con "use namespace: autoclean"?

versione perl

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

sovraccarico versione

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

principale

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; 

stampe

$VAR1 = 12900840; 

La parte peggiore è che non sto ottenendo alcun tipo di avviso o errori nel registro.

UPDATE

Grazie a Freido per trovare il problema. Ho aggiornato la domanda nel caso in cui qualcun altro si imbattesse in questo.

La comunità Perl/Moose generalmente non utilizza il sovraccarico?

risposta

16

namespace::autoclean è inutile con la magia che overload aggiunge per gestire il vostro operatore. I seguenti lavori come ci si aspetterebbe:

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; 

uno sguardo casuale non rivela nulla nei namespace::autoclean documenti che risolve questo, quindi credo che sia una caratteristica inaspettata. Alcune ricerche rivelano che è stato segnalato un bug.

Credo che scende le particolari simboli che overload aggiunge al pacchetto. Il sovraccarico + aggiunge le voci della tabella dei simboli (), (+ e OVERLOAD. Suppongo che alcuni o tutti vengano aspirati dal namespace::autoclean, annullando così il sovraccarico.

Se ti senti avventuroso, here's a patch per namespace::autoclean che filtra i simboli di sovraccarico.

+1

+1 per trovare la soluzione dopo che ho battuto la testa sulla scrivania per un'ora o due cercando di trovare il problema con il mio codice. insensati bug di libreria! – qodeninja

+1

Ci sono stato, l'ho fatto. :) Ero abbastanza sconcertato dal tuo problema fino a quando non mi sono ricordato che 'overload' funzionava inserendo simboli magici, e mi chiedevo se' autoclean' stesse scherzando con loro. – friedo

+3

@nodebunny, perché lamentarsi del codice di altre persone quando puoi scrivere il tuo? :) Questa domanda mi ha ispirato a scrivere [namespace :: sweep] (http://search.cpan.org/~friedo/namespace-sweep/lib/namespace/sweep.pm) che non calpesterà i tuoi sovraccarichi. Maggiori informazioni [qui] (http://blogs.perl.org/users/mike_friedman/2011/10/announcing-namespacesweep.html). – friedo

10

Quindi friedo è assolutamente corretto; il problema sta nella classe euristica: MOP usa per determinare cosa è e cosa non è un "metodo". Generalmente, qualsiasi cosa importata da un altro pacchetto non è un metodo e gli overload tecnicamente si qualificano come tali. Poiché namespace :: autoclean richiede Class :: MOP quali metodi esistono per il pacchetto e rimuove il resto, autoclean cancella ciecamente sovraccarichi insieme a tutto il resto.

Che è piuttosto sorprendente, penso.

MooseX::MarkAsMethods aiuterà con questo per le classi di Moose; viene eseguito prima di autoclean e dice a Moose di riconoscere i simboli del codice di sovraccarico per quel pacchetto come metodi. Ciò risparmia loro l'ascia di autoclean e ha il vantaggio aggiunto che ora puoi usare sovraccarichi nei ruoli, consumarli e farli "funzionare". (Full disclosure: Ho scritto MX :: MarkAsMethods dopo che la mia correzione automatica è stata rifiutata 2 anni fa.)

Tuttavia, questo non aiuta le classi non Moose che si potrebbe desiderare di utilizzare autoclean con ... La rimozione di sovraccarichi da parte di autoclean è, nel migliore dei casi, un difetto in autoclean.

+5

'flaw' è troppo gentile,' namespace :: autoclean' non funziona a causa di questo. La tua correzione è stata perfetta. A proposito, è un peccato che il manutentore sia ostinato a riguardo. –

0

Ho avuto lo stesso problema (cercando di sovraccaricare "" nel mio caso), ma MooseX :: MarkAsMethods non ha ancora funzionato. Non è stato esaminato il motivo per cui ancora correttamente, ma una correzione alternativa che il lavoro ha effettuato era quella di utilizzare MooseX::Role::WithOverloading (e poiché utilizzavo già vari ruoli che si adattano facilmente).

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

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

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