2010-08-29 12 views
0

Je ne suis pas sûr de savoir pourquoi perl ne reconnaît pas la méthode d'ajout de tas. Obtenir un message donné dans le titre de la question. Voici les fichiers les plus pertinents.Impossible de localiser la méthode d'objet "add" via le package "Heap"

#!/usr/bin/perl -w 

use strict; 
use Util; 
use Heap; 
use HuffTree; 

my $heap = Heap->new; 
my $test = 3; 
$heap->add($test); # <--------ERROR HERE----------- 

package Heap; 

use strict; 
use warnings; 

use POSIX(); 

sub new { 
    my $class = shift; 
    my $self = { "aref" => [""], 
      "next" => 1, 
      @_}; 
    bless $self, $class; 
} 


sub print { 
    my $self = shift; 
    my $next = $self->{"next"}; 
    my $aref = $self->{"aref"}; 
    print "array => @$aref\n"; 
    print "next => $next\n"; 
} 


sub compare { 
    my ($self, $i, $j) = @_; 
    my $x = $self->{"aref"}[$i]; 
    my $y = $self->{"aref"}[$j]; 

    if (!defined $x) { 
    if (!defined $y) { 
     return 0; 
    } else { 
     return -1; 
    } 
    } 
    return 1 if !defined $y; 
    return $x->priority <=> $y->priority; 
} 


sub swap { 
    my ($self, $i, $j) = @_; 
    my $aref = $self->{"aref"}; 
    ($aref->[$i], $aref->[$j]) = ($aref->[$j], $aref->[$i]); 
} 


sub add { 
    my ($self, $value) = @_; 
    my $i = $self->{"next"}; 
    $self->{"aref"}[$i] = $value; 

    while ($i > 1) { 
    my $parent = POSIX::floor($i/2); 
    last if $self->compare($i, $parent) <= 0; 
    $self->swap($i, $parent); 
    $i = $parent; 
    } 
    $self->{"next"}++; 
} 


sub reheapify { 
    my ($self, $i) = @_; 
    my $left = 2 * $i; 
    my $right = 2 * $i + 1; 

    my $winleft = $self->compare($i, $left) >= 0; 
    my $winright = $self->compare($i, $right) >= 0; 
    return if $winleft and $winright; 

    if ($self->compare ($left, $right) > 0) { 
    $self->swap($i, $left); 
    $self->reheapify($left); 
    } else { 
    $self->swap($i, $right); 
    $self->reheapify($right); 
    } 
} 


sub remove { 
    my $self = shift; 
    my $aref = $self->{"aref"}; 

    my $result = $aref->[1]; 
    $aref->[1] = pop @$aref; 
    $self->{"next"}--; 

    $self->reheapify(1); 
    return $result; 
} 


sub empty { 
    my $self = shift; 
    return $self->{"next"} == 1; 
} 

1; 

package HuffTree; 

    use warnings; 
    use strict; 

use Pair; 
our @ISA = "Pair"; 


sub priority { 
    my $self = shift; 

    # lowest count highest priority 
    return -$self->{frequency}; 
} 


sub left { 
    my $self = shift; 
    return $self->{left}; 
} 


sub right { 
    my $self = shift; 
    return $self->{right}; 
} 

1; 

package Pair; 

use warnings; 
use strict; 

sub new { 
    my $class = shift; 
    my $self = { @_ }; 
    bless $self, $class; 
} 


sub letter { 
    my $self = shift; 
    return $self->{letter}; 
} 


sub frequency { 
    my $self = shift; 
    return $self->{frequency}; 
} 


sub priority { 
    my $self = shift; 
    return $self->{frequency}; 
} 

1; 

package Util; 

use strict; 
use warnings; 

sub croak { die "$0: @_: $!\n"; } 


sub load_arg_file { 
    my $path_name = shift @ARGV; 
    my $fh; 
    open($fh, $path_name) || croak "File not found.\n"; 
    return $fh; 
} 

1; 
+2

Supprimez toutes les références au code que vous ne montrez pas et fournissez des exemples de données qui déclenchent toujours le problème ou nous ne pouvons pas vous aider beaucoup. – ysth

+0

ce que j'ai dit. Aussi, essayez de simplifier votre programme autant que possible tout en exposant votre problème. –

+0

@Philip Potter: s'il le faisait, il trouverait probablement la réponse sans même demander :) – ysth

Répondre

5

Vous avez un Heap.pm installé à partir du CPAN. C'est ce qui est chargé, pas le vôtre Heap.pm. Le new sous la Heap.pm de CPAN ressemble à ceci:

sub new { 
    use Heap::Fibonacci; 

    return &Heap::Fibonacci::new; 
} 

Ce qui est en fait un bug dans ledit module, car Heap::Fibonacci utilise la chose norme bless \$h, $class; dans son new sous, si la référence est béni dans le Heap paquet, qui n'a en effet pas un sous appelé add (Heap::Fibonacci fait).

Pour résoudre votre problème immédiat, vous pouvez:

  • assurez-vous que votre module est pris avant la « autre » Heap (en modifiant @INC avec use lib, par exemple,
  • ou pas réinventer la roue et effectivement utiliser Heap::Fibonacci).

En tout cas, il pourrait être une bonne idée de signaler ce problème à l'auteur du module Heap - parce que même si vous n'avez pas votre propre Heap.pm, votre code serait toujours pas avec le même message.

+5

La première solution proposée devrait être «si vous voulez réinventer la roue, espacez vos roues de sorte qu'elles ne soient pas en conflit avec le CPAN». 'Heap' devrait être' ApplicationName :: Heap' ou 'OrganizationName :: Heap' ou quelque chose du genre. :) – hobbs

+3

Voir aussi [cette question à propos des noms de modules privés] (http://stackoverflow.com/questions/658955/how-do-i-choose-a-package-name-for-a-custom-perl-module- cela-ne-pas-entrer en collision). – cjm

+0

Merci! Ça a du sens maintenant. @reinventing the wheel, j'apprends Perl alors je voulais juste essayer quelques trucs. – floogads