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

Hallo,
I am trying to figure out how to use my code as .pm modules.

I have some code called /libs/routine.pm
It looks like this;
package routine; our @EXPORT=qw(dostuff); use Exporter; our @ISA=qw(Exporter); use strict; sub dostuff() { my ($scalar,$scalar,$scalar_REF,$scalar)=@_; .. .. ...Do Some Processing... }

I am trying to use this module from the following perl script;
(doit.pl) use lib "/libs"; use routine; dostuff("a","b",\@c,"d");

But I keep getting an error trying to run doit.pl as follows;

To many arguments for routine::dostuff at doit.pl line x near ""d"".
Execution of doit.pl aborted due to compilation errors.

Anyone know why?

Ta, Matthew.

Replies are listed 'Best First'.
Re: use lib "/..." and sub parms..
by Anonymous Monk on Mar 15, 2004 at 17:02 UTC
    To many arguments for routine::dostuff at doit.pl line x near ""d"".
    That's because of the empty prototype you've given your sub:
    sub dostuff()
    
    Take away the parens and you should be fine. "But it worked fine before I put it in a module", you say. That's because putting it in a module changed the order of compilation. Prototypes don't take effect until after they're compiled.

      I'd like to expand on prototyping for a minute. Prototyping is putting a set of parentheses after the name of a sub to specify what types of variables it expects as arguments, and how many variables. Some examples:

      #! /usr/bin/perl use strict; use warnings; # sub without prototypes # use unless you have a reason to prototype sub foobar { # do stuff; } # sub that expects one scalar sub foobaz ($) { # do stuff; } # sub that expects the first argument # to be an array, the second to be a # hash, and the third to be a scalar sub foobarbaz (@, %, $) { # do stuff; }

      There are probably 3 reasons you'd want to prototype:

      1. Speed: If you prototype a function, it becomes a candidate for inlining at compile time. Basically, whenever a function is called, there is some time taken to switch from the current function to the function, and then come back. This time can be eliminated by replacing the code that calls the function with the function's code itself. Before you go out and prototype all your functions for speed, know that this gain is very small, and unless you're doing some really heavy computer work, it's just going to cause confusion.
      2. Mimic strongly typed languages: Languages like Java and C believe that you should have very strict rules for variables -- you declare variables as a certain type and unless you explicitely declare a conversion they are treated as whatever you declare them as. Some people coming over from other languages can find Perls "Do what you mean" style hard to deal with at first (I personally did a lot of silly things when I first learned). You should not consider this to be a Good Reason.
      3. Try to prevent your users from doing something dumb: If your user doesn't read the POD / Manifest and does something dumb, they will get an error (assuming they use strict; and preferably also use warnings;). A lot of times, this can be really unperlish. (For instance, all functions in CGI.pm accept an unlimited number of arguments, and will display each one in turn).

      I hope that helps,

      Vautrin


      Want to support the EFF and FSF by buying cool stuff? Click here.
        Vautrin: You are right about "sub foobar {...}" being the right way to code unless and until you completely understand what Perl calls "prototypes". However, otherwise your post is almost completely false. Specifically:

        • prototypes do not provide checking of argument number and type. They might look like they do, but they don't.

        • the "@" and "%" prototypes do not mean "array" and "hash".

        • the "\@" and "\%" prototypes do not mean "arrayref" and "hashref".

        Once more: prototypes do not provide checking of argument number and type.

        Why even have them then? Good question. Tom Christiansen's prototypes explanation explains the whole situation. It is detailed and crystal-clear.

        If you want to check number and type of arguments, the best way is to do it by hand.

Re: use lib "/..." and sub parms..
by pbeckingham (Parson) on Mar 15, 2004 at 18:17 UTC

    ...or include a real prototype:

    sub dostuff ($$$$) { my ($scalar, $scalar, $scalar_REF, $scalar) = @_; .. .. ...Do Some Processing... }

      You mean:

      sub dostuff ($$\@$) { my ($scalar, $scalar, $scalar_REF, $scalar) = @_; .. .. ...Do Some Processing... }

      I DO hope the use of $scalar in all this is purely symbolic ... besides being pointless to declare the same variable three times, assigning three different values to it at the same time limits your coding options.

      --
      TTTATCGGTCGTTATATAGATGTTTGCA

        Thank you TomDLux, good point. Will my incorrect version therefore accept any scalar, whereas your corrected one specifically requires an array ref?

        If so, then we have several shades of grey between completely and explicitly prototyped down to bareword. I have not been using \@, but just $, so thanks for pointing that out.

Re: use lib "/..." and sub parms..
by eXile (Priest) on Mar 15, 2004 at 21:46 UTC
    <nitpicking>
    Also, the last expression in you module should be:
    1;
    (or something similar that evaluates to 'true'), otherwise you'll get a module-'did not return a true value'-error when you 'use' it.
    </nitpicking>