appu_rajiv has asked for the wisdom of the Perl Monks concerning the following question:

Can anyone explains why the first piece of code is working fine while the second is giving compilation error. Put both piece of codes in different pm files and try to compile it using perl command. The only difference in both the code snippets is order of sub-routines.
First code snippet: Package one.pm
package one; use strict; sub authenticate { my $login = { uname => 'rajiv', pwd => 'rajiv' }; _validate($login); } sub _validate(){ my ($login) = @_; if(($login->{uname} eq 'rajiv') && ($login->{pwd} eq 'rajiv')) { print "Login success"; } else { print "Login failed"; } } 1;
Second code snippet: Package second.pm
package two; use strict; sub _validate(){ my ($login) = @_; if(($login->{uname} eq 'rajiv') && ($login->{pwd} eq 'rajiv')) { print "Login success"; } else { print "Login failed"; } } sub authenticate { my $login = { uname => 'rajiv', pwd => 'rajiv' }; _validate($login); } 1;
Try compiling one.pm on shell.
shell>perl one.pm
shell>

Now try compiling two.pm on shell.
shell>perl two.pm
Too many arguments for two::_validate at two.pm line 21, near "$login)"
Execution of two.pm aborted due to compilation errors.
shell>
Please notice the empty parenthesis after _validate() sub.

Replies are listed 'Best First'.
Re: Strange behavior by Perl: Too many arguments for...
by kennethk (Abbot) on Mar 02, 2010 at 18:41 UTC
    Your issue is that you are using subroutine Prototypes in defining _validate. Prototypes can only be applied when the subroutine is defined prior to usage, so the order affects whether the compiler tests prototypes or not. Since you are not actually using them (and if you were, using them incorrectly), your sub definition should read:

    sub _validate{ my ($login) = @_; if(($login->{uname} eq 'rajiv') && ($login->{pwd} eq 'rajiv')) { print "Login success"; } else { print "Login failed"; } }
Re: Strange behavior by Perl: Too many arguments for...
by FunkyMonk (Bishop) on Mar 02, 2010 at 18:50 UTC
    In your first example, _validate is called before it is defined. That isn't a problem as perl performs a compilation pass of your code before it executes it (oversimplified, I know).

    Your second example is the other way way round. The compiler sees your definition, and its prototype - the empty brackets before the brace in "_validate() {". That prototype says that _validate must be called with no arguments. However, your subroutine call has one argument: $login.

    Removing the empty parentheses from your function definition will solve your problem:

    sub _validate {
Re: Strange behavior by Perl: Too many arguments for...
by AnomalousMonk (Archbishop) on Mar 02, 2010 at 19:28 UTC

    Note also that using warnings will actually cause a warning to be issued when you do this sort of thing. Use of strictures is irrelevant to prototypes.

    >perl -le "use strict; Sa(1); sub Sa () { print 'Sa: ', $_[0] } use warnings; Sb(2); sub Sb () { print 'Sb: ', $_[0] } " main::Sb() called too early to check prototype at -e line 1. Sa: 1 Sb: 2