0

I'm not sure why perl isn't recognizing the Heap's method add. Getting message given in question title. Here are the most relevant files.

#!/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;
floogads
  • 271
  • 2
  • 4
  • 13
  • 2
    Remove all references to code you don't show and provide sample data that still triggers the problem or we can't help you much. – ysth Aug 29 '10 at 20:52
  • what ysth said. Also, try to simplify your program as much as possible while still exhibiting your problem. – Philip Potter Aug 29 '10 at 20:55
  • @Philip Potter: if s/he did that, s/he'd likely find the answer without even asking :) – ysth Aug 29 '10 at 21:24
  • 1
    In your revised code, I removed "use Thing;", "use Util;" and "use HuffTree;", and changed `heap->new` to `Heap->new`. I can't reproduce any error message about finding `add` in package `Heap`, I'm afraid. – Philip Potter Aug 29 '10 at 21:44
  • @floogads: still not enough to run this code here (`HuffTree`, `Thing`). Also, in the first version of the question it was `Heap->new`, now it is `heap->new`, I assume it's a typo? – Grrrr Aug 29 '10 at 21:47
  • Thing isn't necessary. Edited with everything. – floogads Aug 29 '10 at 21:59
  • /me cries at all the boilerplate accessor code. Have you considered using [Moose](http://search.cpan.org/perldoc?Moose)? – Ether Aug 29 '10 at 22:52

1 Answers1

5

You have a Heap.pm installed from CPAN. That's what gets loaded, not your own Heap.pm. The new sub in the Heap.pm from CPAN looks like this:

sub new {
    use Heap::Fibonacci;

    return &Heap::Fibonacci::new;
}

Which is actually a bug in said module, because Heap::Fibonacci uses the standard bless \$h, $class; thing in its new sub, so the reference is blessed into the Heap package, which does indeed not have a sub called add (Heap::Fibonacci does).

To solve your immediate problem, you can:

  • make sure that your module is picked up before the "other" Heap (by modifying @INC with use lib, for example;
  • or not reinvent the wheel and actually use Heap::Fibonacci).

At any rate, it might be a good idea to report this problem to the Heap module author - because even if you did not have your own Heap.pm, your code would still fail with the same message.

Grrrr
  • 2,477
  • 20
  • 21
  • 5
    The first solution offered should be "if you want to reinvent the wheel, namespace your wheels so they don't conflict with CPAN". `Heap` should be `ApplicationName::Heap` or `OrganizationName::Heap` or something of the sort. :) – hobbs Aug 29 '10 at 22:16
  • 3
    Also see [this question about private module names](http://stackoverflow.com/questions/658955/how-do-i-choose-a-package-name-for-a-custom-perl-module-that-does-not-collide). – cjm Aug 29 '10 at 22:23
  • Thanks! Makes sense now. @reinventing the wheel, I'm learning Perl so just wanted to try some stuff out. – floogads Aug 29 '10 at 22:35