1
votes

Question about using the Perl CGI module:

Let's say I have a sub called foo that accepts two parameters defined as follows:

sub foo {
   local($a, $b) = @_;
   print "a= [$a]";
}

In my main routine, I take some form parameters and pass them to foo like this:

use CGI;
$cgi = CGI->new;
foo($cgi->param('field1'), $cgi->param('field2'));

If the form did not pass in a value for field1, (in my case, a SELECT field called field1 with no values to choose from was used), the sub foo sets $a to the value that was passed in $cgi->param('field2'), which was a non-empty value.

Can someone help me understand why this happens and why $a isn't simply a blank ('') value and $b = the value sent in from $cgi->param('field2')?

I'm sure there's a logical reason, but I'm not a Perl pro so I'm sure it's something I've yet to learn or understand about Perl.

Thanks in advance!

1
You should not be using local here (and you should not use $a and $b as variable names as those are specially used for sort.) You want to use my ( $foo, $bar ) = @_; - friedo
Sorry -- I was just using $a and $b to represent any two variables. This was just a made-up example to show what I was trying to accomplish. I never use them as real params inside a sub. I am curious about why local is considered improper for declaring parameter variables being received in a sub though. - Vinnie
Because local is really badly named. It doesn't create local variables. You create localised variables that work as you'd expect them to, always use my. - Dave Cross

1 Answers

3
votes

CGI's param() function behaves differently if called in list or scalar context. In scalar context, the first (and most the only) parameter value is returned. In list context, all parameter values are returned (remember that CGI allows to have multiple values per key).

If you call your function like this, then list context is used. This means that $cgi->param('field1') evaluates to the empty list, and the first value of $cgi->param('field2') is assigned to $a in the subroutine. To avoid this, you have to explicitly force scalar context. This can be done by using scalar:

foo(scalar($cgi->param('field1')), scalar($cgi->param('field2')));

Another possibility is to use intermediate variables:

my $field1 = $cgi->param('field1'); # scalar context here
my $field2 = $cgi->param('field2');
foo($field1, $field2);