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

Greeting fellow monks

Please allow me to ask this potentially very stupid question: are there some trick that makes Perl check the number of arguments given to a sub?

Please do not take my head off for asking this question.

  • Comment on Enforcing formal arguments at compile time?

Replies are listed 'Best First'.
Re: Enforcing formal arguments at compile time?
by tachyon (Chancellor) on May 03, 2002 at 05:19 UTC
Re: Enforcing formal arguments at compile time?
by demerphq (Chancellor) on May 03, 2002 at 09:34 UTC
    I tend to use Carp::Assert for this type of stuff.
    use Carp::Assert; sub foo { is(scalar @_, 2) if DEBUG; }
    That way when your code goes into prodution you can have Perl optimize away the assertions by changing the use to a no
    no Carp::Assert;
    I definately dislike it when code uses prototypes for doing this type of thing. The trade-offs are unacceptable.

    Yves / DeMerphq
    ---
    Writing a good benchmark isnt as easy as it might look.

Re: Enforcing formal arguments at compile time?
by jsprat (Curate) on May 03, 2002 at 05:07 UTC
    Sure- declare your subs at the beginning of your script. For example,

    #!/usr/bin/perl use strict; sub foo($); #declare foo as a sub that accepts #a single scalar, to be defined later foo; #compile time error foo 1; #okay - no error sub foo($) { #actual foo implementation print shift; }

    Update: tachyon rightly points out that this won't always behave as expected - and gives two good links for reference. Perl tries to figure out the context of your arguments, which may (or may not) DWIM.

    sub foo($$); #two scalar arguments foo $bar; #error foo @bar; #error foo $bar, $baz; #ok foo $bar, @baz; #no error, but does it do what you want?

      Actually prototypes don't always work the way you might expect (see links in node below):

      #!/usr/bin/perl use strict; sub foo($); my @ary = (4,3,2); foo(@ary); # no compile time error sub foo($) { print shift }

      Update

      gmax points out I should run my code before posting as I forgot the my to satisfy strict. Ooops :-)

      cheers

      tachyon

      s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

        I expect that in the example you give, foo will be called with a single scalar argument which is a reference to the array @ary. Am I wrong? Or isn't that what you expect?

        Remember arrays are not lists. This is one of those occasions when forgetting that fact can leave you vaguely confused. Of course, if you've been following perl 6 you'd want to write that as foo(*@ary).

        Update: Dang! I am wrong. I didn't expect it to be a compile error, but the direction Perl 6 is taking led me astray as to what would actually happen. Ah well.

Re: Enforcing formal arguments at compile time?
by IlyaM (Parson) on May 03, 2002 at 09:10 UTC
Re: Enforcing formal arguments at compile time?
by Steve_p (Priest) on May 03, 2002 at 12:20 UTC
    Adding this should give you the count
    my $argCnt = @_;