Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Undefined subroutine &main::

3,672 views
Skip to first unread message

Weizhong Dai

unread,
May 24, 2010, 6:49:54 AM5/24/10
to begi...@perl.org
Hi guys, I met a problem.
When I tried this script below:

//--------------------------------------------------------------------
sub print_instruction {
my ($disk, $start, $end) = @_;
print "Move disk #$disk from $start to $end.\n";
}

sub hanoi {
my ($n, $start, $end, $extra, $m) = @_;
if ($n == 1) {
$m->(1, $start, $end);
} else {
hanoi($n-1, $start, $extra, $end);
$m->($n, $start, $end);
hanoi($n-1, $extra, $end, $start);
}
}

&hanoi(3, 'A', 'C', 'B', \&print_instruction);
//-------------------------------------------------------------------------

I got a error : Undefined subroutine &main:: called at ....
this is an example in <High Order Perl>, so it should not be wrong, I
just don't known what is the problem.
Plz help me.

Rob Coops

unread,
May 24, 2010, 7:23:56 AM5/24/10
to begi...@perl.org

> --
> To unsubscribe, e-mail: beginners-...@perl.org
> For additional commands, e-mail: beginne...@perl.org
> http://learn.perl.org/
>
>
>
No idea why Perl would cry about &main, my knowledge of Perl internals is
not that good yet. But I would bet that the problem lies in the following:

sub hanoi expects to receive 5 parameters, in side the sub you are calling
is once again but now with only 4 parameters.

hanoi($n-1, $start, $extra, $end);
$m->($n, $start, $end);
hanoi($n-1, $extra, $end, $start);

My guess is that Perl when you are pulling in the parameters using the my (
... ) = @_; line at the beginning of the sub places a ref to main at the end
for your convenience, thus the call to $m-> will be interpreted as a call to
&main which in turn upsets Perl.

I would try to hand in $m in the two recursive calls inside the hanoi sub.

hanoi($n-1, $start, $extra, $end, $m);
$m->($n, $start, $end);
hanoi($n-1, $extra, $end, $start, $m);

That should do the trick...

Don't trust the written word, in the end it was a human doing the writing so
mistakes are inevitable. ;-)

Regards,

Rob

Philip Potter

unread,
May 24, 2010, 8:02:01 AM5/24/10
to Weizhong Dai, begi...@perl.org

You didn't "use strict". If you turn on use strict, the problem
becomes much clearer:

Can't use string ("") as a subroutine ref while "strict refs" in
use at weizhong.pl line 10.

Line 10, in my copypasted script, is this:

$m->(1, $start, $end);

$m is being used as a sub ref but it's complaining that $m is a
string. As Rob Coops accurately pointed out, this is because you
aren't passing enough arguments in the recursive call:

hanoi($n-1, $start, $extra, $end);

So I have two questions for you:
1) Do you know about "use strict" and "use warnings"? do you aspire to
*always* use them?
2) Is this *really* the exact code from HOP? Does HOP make the same
mistake? If so, is it documented at the HOP errata page? If not, where
did you go wrong in copying from the book?

Incidentally, the original error message:

Undefined subroutine &main:: called at ....

is caused by the same error. Without "use strict 'refs'", a string can
be used as a subref, so for example you can say:

my $ref = 'foo';
$ref->(); # same as foo();

$m is uninitialized, and its value is converted to the empty string
"", and then the subroutine in package "main" with name "" is called,
i.e. the subroutine "&main::". This subroutine doesn't exist, which
causes the error message seen.

If you "use warnings" as well, you also get the warning

Use of uninitialized value in subroutine entry at ....

which warns you that $m is uninitialised.

Phil

0 new messages