Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Perl Module

by pparesh (Initiate)
on Dec 31, 2008 at 04:49 UTC ( #733408=perlquestion: print w/ replies, xml ) Need Help??
pparesh has asked for the wisdom of the Perl Monks concerning the following question:

In a perl module, i have a function as below, sub Report ($;$) { ($package, $filename, $line, $subr) = caller; ... ... } I would like to know, why there are $ symbols present in the argument of function Report above?

Comment on Perl Module
Re: Perl Module
by Lawliet (Curate) on Dec 31, 2008 at 04:53 UTC

    Those are called prototypes. A general rule of thumb is that if you do not know why you would need them, don't use them. (Note that this is the reason I cannot lucubrate :P)

    And you didn't even know bears could type.

Re: Perl Module
by sflitman (Hermit) on Dec 31, 2008 at 05:23 UTC
    That's a prototype which means Report takes one or two scalars, the semicolon separates required from optional arguments. Prototypes do cool things like adding new syntax to Perl and compile-time checking of parameter lists.

    HTH, SSF

      ... and are best left alone, unless you know what you are doing.

      One thing they DO NOT do is compile-time (or even run-time) checking of the arguments in the argument-list.

      Consider the following:

      sub test_noproto {print shift;}; sub test_proto ($) {print shift;}; $scalar = 'A'; @array = qw /X Y Z/; %hash = ('key', 'value'); test_noproto($scalar); # gives as expected: A test_noproto(@array); # gives as expected: X test_noproto(%hash); # gives as expected: key test_proto($scalar); # gives as expected: A test_proto(@array); # gives: 3 Did you expect that? test_proto(%hash); # gives: 1/8 Did you expect that?
      In some way (but not in others) one can say that the $ prototype magically causes the argument to the sub to be evaluated in scalar context. This all happens silently without any warning or error to the user. Saying (as perlsub does) "Perl supports a very limited kind of compile-time argument checking using function prototyping." is misleading to the unwary.

      CountZero

      A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

        actually test_proto(@array); was predictable , it's test_proto(%hash); that was not , is there any explanation of "1/8" value or is it just sci-fi ? also,is there any way of using parameters to functions as you do in C or C++ ? I mean you just write down the prototype and the argument names are implicitly taken to be variables which have the scope of the function to which they are arguments of ?
      I would describe it rather differently. I would say that prototypes give people new ways of creating bugs while being mislead into thinking that they are doing something that is potentially good.
Re: Perl Module
by lakshmananindia (Chaplain) on Dec 31, 2008 at 08:21 UTC

    Example that I saw in a page is as follows

    sub f($$); //Function declaration.
    @a = (5, 9);
    Now we will see what will happen for different calls.

    &f; The & bypasses subroutine prototypes, so the compiler won't complain about the subroutine call. The call also has no argument list, so it is called with its caller's @_.

    &f(); f is called with an empty argument list. The & causes the subroutine prototypes to be bypassed.

    f(); It won't compile because the prototype mismatch.

    f; It won't compile again.

    f(@a); It won't compile because the argument expected is scalars but passed is an array.

    f(@a, @a); This will compile. The compiler interprets the @a in scalar context, so it will pass the no:of:elements in the array to the function.

    &f(@a); This also compiles. The & disables prototype checking, so @a becomes the @_ of the subroutine. This is equivalent to f(5,9).

      f(@a); It won't compile because the argument expected is scalars but passed is an array.
      That is not correct. The actual error message is "Not enough arguments for main::f at ...". Perl prototyping does not care about the type of the arguments. It only checks the number of arguments and does so in a totally broken way. As arguments into a sub are passed in as a flat list, passing a list or array with two elements should be no different as passing two scalars.

      perlsub says so explicitly:

      The Perl model for function call and return values is simple: all functions are passed as parameters one single flat list of scalars, and all functions likewise return to their caller one single flat list of scalars. Any arrays or hashes in these call and return lists will collapse, losing their identities

      CountZero

      A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

        Perl prototyping does not care about the type of the arguments

        Not true:
        #!/usr/bin/perl use strict; use warnings; sub mysub (\@) { my $arg = $_; print ref $arg."\n"; } my (@array, %hash, $scalar); mysub (\@array); mysub (\%hash); mysub (\$scalar); mysub (@array); # This is the only one which compiles mysub (%hash); mysub ($scalar); mysub (qw(This is a list));
        Gives (5.10):
        Type of arg 1 to main::mysub must be array (not reference constructor) + at C:\gash.pl line 15, near "@array)" Type of arg 1 to main::mysub must be array (not reference constructor) + at C:\gash.pl line 16, near "%hash)" Type of arg 1 to main::mysub must be array (not single ref constructor +) at C:\gash.pl line 17, near "$scalar)" Type of arg 1 to main::mysub must be array (not private hash) at C:\ga +sh.pl line 20, near "%hash)" Type of arg 1 to main::mysub must be array (not private variable) at C +:\gash.pl line 21, near "$scalar)" Type of arg 1 to main::mysub must be array (not list) at C:\gash.pl li +ne 23, near "qw(This is a list))" Execution of C:\gash.pl aborted due to compilation errors.
Re: Perl Module
by cdarke (Prior) on Dec 31, 2008 at 10:00 UTC
    Prototypes in Perl do not do the same thing as prototypes in C/C++ (mind you, that's an area that is mis-understood as well). In Perl they force the context of the arguments, not the number and type. This is the core of most misunderstandings about prototypes.

    Report takes one or two scalars
    Is better written as Report takes one or two arguments in scalar context

    Personally I find them useful for reference arguments, for example mysub(\@\%). This will generate a compile-time error if the wrong type is passed. Otherwise you have to use ref to check, and the best you can do is report a run-time error.

    Their main drawback is that they are so easily circumvented, for example using OO method calls, or prefixing the call with &.

    Finally, for the OP, despite all the bad news about prototypes, if it ain't broke don't fix it. Please don't remove the prototype from the module! Just don't use them without a damn good reason.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://733408]
Approved by Lawliet
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (10)
As of 2014-09-17 06:50 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (62 votes), past polls