Error when using coderefs.

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • barrientos101
    New Member
    • Feb 2007
    • 4

    Error when using coderefs.

    Hello,

    I am trying some code from Higher Order Perl by Mark Jason Dominus and it doesn't work. When I tried to replace the original print statements with a reference to a subroutine (print_instruct ion) that prints, I kept getting the error message "Undefined subroutine &main:: called at hanoi.pl line 27." Line 27 is marked in the code below in a comment (it shows as line 21 in the posting below). It doesn't like the dereferencing of the subroutine reference I passed in. This was cut and pasted from his website. The only things I added were the print_instructi on subroutine and its calls, going strictly by what's in the book.

    I am using Perl 5.8.8, ActiveState build 820, built Jan. 23, 2007 on Windows XP.

    Code:
    # hanoi(N, start, end, extra)
    # Solve Tower of Hanoi problem for a tower of N disks,
    # of which the largest is disk #N.  Move the entire tower from
    # peg 'start' to peg 'end', using peg 'extra' as a work space
    
    sub print_instruction
    {
        my ($disk, $start, $end) = @_;
        
        print "Move disk #$disk from $start to $end.\n";
    }
    
    hanoi(3, 'A', 'C', 'B', \&print_instruction);
      
    sub hanoi
    {
        my ($n, $start, $end, $extra, $move_disk) = @_;
        
        if ($n == 1)
        { 
            $move_disk->(1, $start, $end);  # line 27
        } 
        else 
        {
            hanoi($n-1, $start, $extra, $end);             # Step 2
            $move_disk->($n, $start, $end);
            hanoi($n-1, $extra, $end, $start);             # Step 4
        }
    }
    
    sub print_instruction
    {
        my ($disk, $start, $end) = @_;
        
        print "Move disk #$disk from $start to $end.\n";
    }
  • barrientos101
    New Member
    • Feb 2007
    • 4

    #2
    Oops, please don't be put off in the above post by the fact that I have two print_instructi on subroutines defined. This is not the case in practice. I just copied that code above the call to hanoi() without deleting it from below. Thanks.

    Comment

    • KevinADC
      Recognized Expert Specialist
      • Jan 2007
      • 4092

      #3
      Originally posted by barrientos101
      Hello,

      I am trying some code from Higher Order Perl by Mark Jason Dominus and it doesn't work. When I tried to replace the original print statements with a reference to a subroutine (print_instruct ion) that prints, I kept getting the error message "Undefined subroutine &main:: called at hanoi.pl line 27." Line 27 is marked in the code below in a comment (it shows as line 21 in the posting below). It doesn't like the dereferencing of the subroutine reference I passed in. This was cut and pasted from his website. The only things I added were the print_instructi on subroutine and its calls, going strictly by what's in the book.

      I am using Perl 5.8.8, ActiveState build 820, built Jan. 23, 2007 on Windows XP.

      Code:
      # hanoi(N, start, end, extra)
      # Solve Tower of Hanoi problem for a tower of N disks,
      # of which the largest is disk #N.  Move the entire tower from
      # peg 'start' to peg 'end', using peg 'extra' as a work space
      
      sub print_instruction
      {
          my ($disk, $start, $end) = @_;
          
          print "Move disk #$disk from $start to $end.\n";
      }
      
      hanoi(3, 'A', 'C', 'B', \&print_instruction);
        
      sub hanoi
      {
          my ($n, $start, $end, $extra, $move_disk) = @_;
          
          if ($n == 1)
          { 
              $move_disk->(1, $start, $end);  # line 27
          } 
          else 
          {
              hanoi($n-1, $start, $extra, $end);             # Step 2
              $move_disk->($n, $start, $end);
              hanoi($n-1, $extra, $end, $start);             # Step 4
          }
      }
      
      sub print_instruction
      {
          my ($disk, $start, $end) = @_;
          
          print "Move disk #$disk from $start to $end.\n";
      }
      I don't see a problem with the code and It works for me. This is the correct syntax to use with a code reference:

      $move_disk->(1, $start, $end)

      So I am not sure what the problem is.

      Comment

      • barrientos101
        New Member
        • Feb 2007
        • 4

        #4
        Below I post the answer as given me by Mark Jason Dominus, the author of "Higher Order Perl" himself. This is the complete text of his reply to my e-mail, quoted here with permission. His reply not only includes the correction to my code, but in doing so clearly explains the cryptic error message as well. I wanted to post it as warning of the kinds of problems one can run into when using recursion if one is not careful.


        > I posted this on the web with the code and got only one response. He said
        > that he saw nothing wrong with it and that it worked for him.

        if he says it worked for him, he's lying.

        Here's the problem. hanoi() now takes five arguments.

        Here you call it with five arguments:

        > hanoi(3, 'A', 'C', 'B', \&print_instruc tion);

        And here it prepares to receive the five arguments:

        > sub hanoi
        > {
        > my ($n, $start, $end, $extra, $move_disk) = @_;


        But here you call it with only four arguments:

        > hanoi($n-1, $start, $extra, $end); # Step 2
        > $move_disk->($n, $start, $end);
        > #print "Move disk #$n from $start to $end.\n"; # Step 3
        > hanoi($n-1, $extra, $end, $start); # Step 4


        So after the first call, the subsequent calls to hanoi() leave
        $move_disk undefined.

        Comment

        • KevinADC
          Recognized Expert Specialist
          • Jan 2007
          • 4092

          #5
          Originally posted by barrientos101
          Below I post the answer as given me by Mark Jason Dominus, the author of "Higher Order Perl" himself. This is the complete text of his reply to my e-mail, quoted here with permission. His reply not only includes the correction to my code, but in doing so clearly explains the cryptic error message as well. I wanted to post it as warning of the kinds of problems one can run into when using recursion if one is not careful.


          > I posted this on the web with the code and got only one response. He said
          > that he saw nothing wrong with it and that it worked for him.

          if he says it worked for him, he's lying.

          Here's the problem. hanoi() now takes five arguments.

          Here you call it with five arguments:

          > hanoi(3, 'A', 'C', 'B', \&print_instruc tion);

          And here it prepares to receive the five arguments:

          > sub hanoi
          > {
          > my ($n, $start, $end, $extra, $move_disk) = @_;


          But here you call it with only four arguments:

          > hanoi($n-1, $start, $extra, $end); # Step 2
          > $move_disk->($n, $start, $end);
          > #print "Move disk #$n from $start to $end.\n"; # Step 3
          > hanoi($n-1, $extra, $end, $start); # Step 4


          So after the first call, the subsequent calls to hanoi() leave
          $move_disk undefined.
          Well, he is also wrong, because here is your original code (less the duplicate function):

          Code:
          sub print_instruction
          {
              my ($disk, $start, $end) = @_;
              
              print "Move disk #$disk from $start to $end.\n";
          }
          
          hanoi(1, 'A', 'C', 'B', \&print_instruction);
            
          sub hanoi
          {
              my ($n, $start, $end, $extra, $move_disk) = @_;
              
              if ($n == 1)
              { 
                  $move_disk->(1, $start, $end);  # line 27
              } 
              else 
              {
                  hanoi($n-1, $start, $extra, $end);             # Step 2
                  $move_disk->($n, $start, $end);
                  hanoi($n-1, $extra, $end, $start);             # Step 4
              }
          }
          It works just like that, all I did was change the 3 to a 1 here:

          hanoi(1, 'A', 'C', 'B', \&print_instruc tion);

          I admit I did not go far enough to test the code, but the author calling me a liar seems rather obtuse. My test was just faulty in that all I did was confim the coderef worked the way you had it, I was not testing the logic of your code for all errors. So forgive me for not being thorough, but I answer many questions on many forums and I sometimes am too hasty.

          Comment

          Working...