CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Beginner:
Anomaly with Perl Prototypes

 



Cupidvogel
Novice

Mar 26, 2012, 11:17 AM

Post #1 of 8 (1272 views)
Anomaly with Perl Prototypes Can't Post

Hi, the following code uses prototypes to let me enjoy parentheses-less functions. I intend to pass only two parameters from the list defined after the function invocation (without parentheses). Since I have set the prototype to $$ in the function definition, I guessed the correct output should be (4,5,6). But what I am getting is an error message like this:


Code
Too many arguments for main::coo at sr3.pl line 7, near "4)" 
Execution of sr3.pl aborted due to compilation errors.


Can anyone spot the bug? The code is as follows:


Code
sub coo($$) { return @_ + (1,2); } 
@d = (coo 1,2,3,4);



BillKSmith
Veteran

Mar 26, 2012, 2:08 PM

Post #2 of 8 (1269 views)
Re: [Cupidvogel] Anomaly with Perl Prototypes [In reply to] Can't Post

Your prototyupe requires coo to have exactly two scalar arguments. Your call to the subroutine coo has four arguments, hence the message "Too many arguments for main::coo at sr3.pl ".



Prototypes are almost never useful in perl. They do not mean what we all first think. Refer to the prototype section of perldoc perlsub for their intended purpose.

The synopsis of the same document tells us that parenthesis in subroutine references are optional if the subroutine is predeclared. In your case, it is.

Without prototypes, your function returns the scalar value 6. (i.e. The length of the input array plus the length of the list (1,2).) This is stored in the first element of the array @d.


Code
use strict; 
use warnings;
sub coo { return @_ + ( 1, 2 ); }
my @d = ( coo 1, 2, 3, 4 );
print $d[0];

Good Luck,
Bill


Cupidvogel
Novice

Mar 26, 2012, 2:11 PM

Post #3 of 8 (1268 views)
Re: [BillKSmith] Anomaly with Perl Prototypes [In reply to] Can't Post

No no, I know fully well that I am adding two arrays inside the subroutine, which, because both arrays have length of 2 each will yield 4. (In fact that is a dummy statement to return something. I might as well use return 456!) And as for the removal of (3,4), that's the point, the code ought to store the array (4,3,4) in @d, 4 from the subroutine (which returns the result of the array addition, and because $$ is mentioned as prototype, the subroutine should consider only the parameters 1 and 2 from the list (1,2,3,4) to be considered into its arguments list) and (3,4) from the remaining values, resulting in @d having a value of (4,3,4).


budman
User

Mar 26, 2012, 2:38 PM

Post #4 of 8 (1266 views)
Re: [Cupidvogel] Anomaly with Perl Prototypes [In reply to] Can't Post

 
Prototypes are not used to slice the parameter array.
They are just used for validation.

You are telling it only to accept 2 scalars, thats all, anything else die.
You need to change it to: $$;@ which means 2 scalars '$$' are required, anything else '@' is considered optional ';'


Code
perl -le 'sub coo ($$;@){(@x[0..1],@y)=@_;return (@x + (1,2), @y); }; @d=(coo 1,2,3,4);print "@d"' 
4 3 4


Once it makes it past validation, you need to slice the array yourself.
Assign the first two items to the first array @x, and the rest if any to the second array @y. Then the return should be built with the array addition element first, then append the remaining if any.

That's not a bug - check over the perldoc perlsub docs on Prototypes and how to use them.


Cupidvogel
Novice

Mar 26, 2012, 2:43 PM

Post #5 of 8 (1263 views)
Re: [budman] Anomaly with Perl Prototypes [In reply to] Can't Post

Can you please explain what the statement 2 scalars '$$' are required, anything else '@' is considered optional mean? There are a lot of such cryptic protypal examples in the perldoc page, I understood almost none of them. Where can I get a solid idea of what those cryptic prototypes actually mean?


budman
User

Mar 26, 2012, 4:02 PM

Post #6 of 8 (1259 views)
Re: [Cupidvogel] Anomaly with Perl Prototypes [In reply to] Can't Post

 
The docs explain each item, scroll down the docs to prototypes (about 70% or so).

They all stand for the sigel ($@%&*) in each Perl type:
myref $var
myref @array
myref %hash
myref &sub
myref *glob

The semi-colon ';' means anything else that follows is optional

To be honest, you really don't need them here. They are only used for validation, and have no effect on the subroutine. However, they will prevent the sub from running if the parameters being passed do not match the order of types provided.

The prototype ($$;@) means the first two parameters $$ should be scalar values (1, "abc"), then the semi-colon ; states that all remaining parameters are optional, thus we need to say treat them like an array @ because we do not know how many additional parameters will be included.


FishMonger
Veteran / Moderator

Mar 26, 2012, 5:51 PM

Post #7 of 8 (1253 views)
Re: [budman] Anomaly with Perl Prototypes [In reply to] Can't Post

Prototypes do not validate the args, they just give a "hint" to perl as to what type of data is being passed.

If you pass $var to a prototyped sub, perl does not know if meant to pass a plain simple scalar, or a reference.


Code
use strict; 
use warnings;

sub add;

my $number = { int => 4, real => 1.5 };

my $total = add $number, 7;

print "$total\n";

sub add ($$) {
return $_[0] + $_[1];
}


That won't generate any errors or warnings and can/will introduce a bug which could be difficult to track down in larger scripts.

Point of the story is that you shouldn't use prototypes until you actually NEED them and fully understand how to use them properly.


(This post was edited by FishMonger on Mar 26, 2012, 5:52 PM)


budman
User

Mar 26, 2012, 11:07 PM

Post #8 of 8 (1241 views)
Re: [FishMonger] Anomaly with Perl Prototypes [In reply to] Can't Post

I guess 'argument checking' better describes than 'validate'. True it doesn't actually inspect the contents, just that it match the declared types.

The OP is calling the function with 4 args, which does cause an error. That's why I suggested to add the optional separator ';' to avoid any errors and allow as many extra args as needed.

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives