return and undef

Discussion in 'Perl Misc' started by Dave, Oct 4, 2005.

  1. Dave

    Dave Guest

    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
    Dave, Oct 4, 2005
    #1
    1. Advertising

  2. Dave

    Guest

    "Dave" <> wrote:
    > 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

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
    , Oct 4, 2005
    #2
    1. Advertising

  3. Dave

    Paul Lalli Guest

    Dave wrote:
    > 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
    Paul Lalli, Oct 4, 2005
    #3
  4. Dave

    Matija Papec Guest

    X-Ftn-To: Dave

    "Dave" <> wrote:
    >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



    --
    Matija
    Matija Papec, Oct 4, 2005
    #4
  5. Dave

    Dave Guest

    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;
    }
    Dave, Oct 4, 2005
    #5
  6. Dave

    Anno Siegel Guest

    Dave <> wrote in comp.lang.perl.misc:
    > 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
    --
    If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers.
    Anno Siegel, Oct 4, 2005
    #6
  7. Dave

    Paul Lalli Guest

    Dave wrote, without quoting any context:
    > Harsh.


    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
    Paul Lalli, Oct 4, 2005
    #7
  8. Dave <> wrote:
    > 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.

    --
    Darren Dunham
    Senior Technical Consultant TAOS http://www.taos.com/
    Got some Dr Pepper? San Francisco, CA bay area
    < This line left intentionally blank to confuse you. >
    Darren Dunham, Oct 4, 2005
    #8
  9. "Dave" <> wrote in news:1128441020.495475.143350
    @f14g2000cwb.googlegroups.com:

    > Harsh.


    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

    --
    A. Sinan Unur <>
    (reverse each component and remove .invalid for email address)

    comp.lang.perl.misc guidelines on the WWW:
    http://mail.augustmail.com/~tadmc/clpmisc/clpmisc_guidelines.html
    A. Sinan Unur, Oct 5, 2005
    #9
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Vikas Yadav
    Replies:
    0
    Views:
    1,115
    Vikas Yadav
    Sep 9, 2003
  2. karthikbalaguru
    Replies:
    3
    Views:
    2,995
    Chris Dollin
    Nov 27, 2008
  3. deepak p
    Replies:
    1
    Views:
    130
    Martien Verbruggen
    Jul 10, 2003
  4. Tim McDaniel

    undef($foo) versus $foo = undef()?

    Tim McDaniel, Aug 19, 2009, in forum: Perl Misc
    Replies:
    6
    Views:
    136
    Peter J. Holzer
    Aug 19, 2009
  5. Willem
    Replies:
    62
    Views:
    626
    Ilya Zakharevich
    Sep 9, 2011
Loading...

Share This Page