return and undef

D

Dave

Hi,

I've searched around perldoc and the web. I can't seem to find any
subroutine that ends like:

return %FORM;
undef %FORM;

Does the return statement effectively exit the subroutine? What can you
do if you want to undef that private variable after it is returned?

Thanks,
~dave
 
X

xhoster

Dave said:
Hi,

I've searched around perldoc and the web. I can't seem to find any
subroutine that ends like:

return %FORM;
undef %FORM;

Does the return statement effectively exit the subroutine?

Yes. The undef will not be executed.
What can you
do if you want to undef that private variable after it is returned?

What can I do if I want to paint love green and paint justice orange?

You want to do something that doesn't make any sense.

Xho
 
P

Paul Lalli

Dave said:
I've searched around perldoc and the web. I can't seem to find any
subroutine that ends like:

return %FORM;
undef %FORM;

I would certainly hope not. That would be rather broken code.
Does the return statement effectively exit the subroutine?

Not only "effectively", but literally, figuratively, really, and
intentionally as well. That is the *entire* point of the return
statement: to exit the subroutine, returning the given value to the
caller.

perldoc -f return
What can you do if you want to undef that private variable after it is
returned?

Your question is non-sensical. A private (which in Perl is spelled
"lexical") variable declared in a subroutine falls out of scope at the
end of the subroutine. Not only is it automatically undefined, it
ceases to exist entirely.

Perhaps it's time for you tell us what you're *actually* trying to do,
rather than asking us how to make work the method you've decided upon
to accomplish your goal.

Paul Lalli
 
M

Matija Papec

X-Ftn-To: Dave

Dave said:
I've searched around perldoc and the web. I can't seem to find any
subroutine that ends like:

return %FORM;
undef %FORM;

Does the return statement effectively exit the subroutine? What can you
do if you want to undef that private variable after it is returned?

Usually (perhaps always) you don't need to do that as scoping takes care of
it; please check:
http://perl.plover.com/FAQs/Namespaces.html
or perldoc -q scoping
 
D

Dave

Harsh.

I have a routine (below) that I call from a main program which then
calls a subroutine. This subroutine also calls the form_parse
subroutine.

When I call the form_parse subroutine from the second subroutine, the
value of $FORM{'something'} was "X|X" instead of simply "X". This means
that the local variable %FORM is not ceasing to exist after I return
%FORM and it is seeing a previous value for $FORM{'something'} and
adding to it (per my commented line "this line")

I can solve the problem by adding an undef %FORM at the top of the
subroutine, but that seems silly to have to do. Is that my only
work-around? What am I missing?

Thanks,
~dave



sub form_parse
{
#print "Content-type: text/html\n\n";
undef %FORM;
read (STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
if (length($buffer) < 5)
{$buffer = $ENV{QUERY_STRING};}
my @pairs = split(/&/, $buffer);

foreach my $pair (@pairs)
{
my ($name, $value) = split(/=/, $pair);
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$value =~ s/'/\\'/g;
chomp $value;
if (exists $FORM{$name}){$FORM{$name}.="|$value";} #this line
else {$FORM{$name} = $value;}
}

undef @pairs;
undef $name;
undef $value;
undef $pair;

return %FORM;
undef %FORM;
}
 
A

Anno Siegel

Dave said:
Harsh.

I have a routine (below) that I call from a main program which then
calls a subroutine. This subroutine also calls the form_parse
subroutine.

When I call the form_parse subroutine from the second subroutine, the
value of $FORM{'something'} was "X|X" instead of simply "X". This means
that the local variable %FORM is not ceasing to exist after I return
%FORM and it is seeing a previous value for $FORM{'something'} and
adding to it (per my commented line "this line")

%FORM is *not* a local variable, but a global package variable, and
that is exactly the problem. Declare it lexical with "my" and the
problem will go away. While you're at it, put "use strict; use warnings;"
near the top of your script. You will then have to declare all variables
lexically, which is a good thing.

That said, you should really not try to implement your own CGI, as you do
with form_parse(), except (perhaps) for an exercise. Things aren't as
simple as your code assumes. Other posters, better versed with CGI than
I am, will very probably point out a few things that can go wrong.

Use CGI.pm instead, where the finer points have been taken into
consideration and the bugs ironed out.

Anno
 
P

Paul Lalli

Dave wrote, without quoting any context:

I respectfully disagree.
I have a routine (below) that I call from a main program which then
calls a subroutine. This subroutine also calls the form_parse
subroutine.

Why? Why would you ever need to parse the form twice?
When I call the form_parse subroutine from the second subroutine, the
value of $FORM{'something'} was "X|X" instead of simply "X". This means
that the local variable %FORM

This is consistent with what you originally said:
Does the return statement effectively exit the subroutine? What can you
do if you want to undef that private variable after it is returned?

Unfortunately, they're both wrong, as there are no
local/lexical/private variables anywhere in your code.
is not ceasing to exist after I return
%FORM and it is seeing a previous value for $FORM{'something'} and
adding to it (per my commented line "this line")

Of course it's not. Global variables, like %FORM, are just that -
global. They don't cease to exist until the end of the program.
I can solve the problem by adding an undef %FORM at the top of the
subroutine, but that seems silly to have to do. Is that my only
work-around? What am I missing?

The Posting Guidelines for this group, for one. They would tell you to
enable strict and warnings. That would force you to declare your
variables lexically (or declare the ability to not fully-qualify them
with 'our' - but don't do that).
And CGI.pm, for another.
sub form_parse
{
#print "Content-type: text/html\n\n";
undef %FORM;
read (STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
if (length($buffer) < 5)
{$buffer = $ENV{QUERY_STRING};}
my @pairs = split(/&/, $buffer);

foreach my $pair (@pairs)
{
my ($name, $value) = split(/=/, $pair);
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$value =~ s/'/\\'/g;
chomp $value;
if (exists $FORM{$name}){$FORM{$name}.="|$value";} #this line
else {$FORM{$name} = $value;}
}

undef @pairs;
undef $name;
undef $value;
undef $pair;

return %FORM;
undef %FORM;
}

The entirety of this subroutine can be better written:
use CGI qw/:cgi-lib/;
my %FORM = Vars();
s/\0/|/g for values %FORM;

Re-inventing the wheel seldom has any real benefit.

Paul Lalli
 
D

Darren Dunham

Dave said:
When I call the form_parse subroutine from the second subroutine, the
value of $FORM{'something'} was "X|X" instead of simply "X". This means
that the local variable %FORM is not ceasing to exist after I return
%FORM and it is seeing a previous value for $FORM{'something'} and
adding to it (per my commented line "this line")
I can solve the problem by adding an undef %FORM at the top of the
subroutine, but that seems silly to have to do. Is that my only
work-around? What am I missing?

In your other post you referred to %FORM as a private variable and
others answered you in that context. But nowhere in your code do you
declare it as such. So instead of a private variable it's a global
variable.
sub form_parse
{
#print "Content-type: text/html\n\n";
undef %FORM;

Probably want 'my %FORM;' instead. Indeed for all the variables.
 
A

A. Sinan Unur


What is harsh?

Please provide an appropriate amount of context when posting a follow-
up. Please read the posting guidelines for this group.
What am I missing?

You should use CGI.pm.
sub form_parse
{
#print "Content-type: text/html\n\n";
undef %FORM;
read (STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
if (length($buffer) < 5)
{$buffer = $ENV{QUERY_STRING};}

You should not rely on the amount of data passed to distinguish between
GET and POST. There is the REQUEST_METHOD environment variable for that
purpose.
my @pairs = split(/&/, $buffer);

What if the script is called with:

http://unur-test:8080/cgi-bin/z.pl?param1=t;param2=3
undef @pairs;
undef $name;
undef $value;
undef $pair;

None of this would be necessary if you had proper lexical variables.
return %FORM;
undef %FORM;

The last line will not be executed.

use CGI.pm.

Sinan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,790
Messages
2,569,637
Members
45,348
Latest member
RoscoeNevi

Latest Threads

Top