Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Where to declare?

by Rich36 (Chaplain)
on Oct 24, 2001 at 21:42 UTC ( #121210=perlquestion: print w/replies, xml ) Need Help??

Rich36 has asked for the wisdom of the Perl Monks concerning the following question:

Part of the piece of code I'm working on involves getting a list of valid directories from the user. The problem that I'm having is this...
The code below works, but I get a error message stating.
Variable "@dirlist" will not stay shared at test.pl line 17. Variable "@dirlist" will not stay shared at test.pl line 24.

Where/how do I declare that variable to avoid that warning? If I place the "my @dirlist" within the "getAns()" sub, it redeclares the variable and erases any information that was added. If I leave it out of that sub, I get that warning.

#!/usr/bin/perl -w use strict; my @dirs = &getDirs(); sub getDirs() { my @dirlist; # PROBLEM!!! sub getAns() { print qq(Enter a valid directory: ); chomp(my $ans = <STDIN>); if ($ans ne "") { if ($ans =~ m/foo/g) { push(@dirlist, $ans); &getAns; } else { print qq(That is not a valid directory!\n); &getAns; } } else { return @dirlist; } } } my @dirs = &getAns(); if (@dirs) { return @dirs; } else { die qq(No directories have been entered!\n); } }

Thanks in advance for the help,
Rich36

Replies are listed 'Best First'.
Re: Where to declare?
by Masem (Monsignor) on Oct 24, 2001 at 21:58 UTC
    Not the specific answer to your problem, but do you really need a nested sub for this application? A while loop is much much easier to build around than this. KISS. eg:
    my @dirlist; print qq(Enter a valid directory); chomp (my $ans = <STDIN>); while ( $ans ne "" ) { if ( $ans =~ m/foo/g ) { push @dirlist, $ans; } else { print qq(That is not a valid dir); } print qq(Enter a valid directory); chomp ($ans = <STDIN>); } # @dirlist is now filled happily

    -----------------------------------------------------
    Dr. Michael K. Neylon - mneylon-pm@masemware.com || "You've left the lens cap of your mind on again, Pinky" - The Brain
    "I can see my house from here!"
    It's not what you know, but knowing how to find it if you don't know that's important

      As an aside to your suggestion, I remember a programming course that taught recursion before loops and then taught while loops as an alternative to the "more natural" tail recursion. Interesting what some consider "simple".

      --traveler

Re: Where to declare?
by blackmateria (Chaplain) on Oct 24, 2001 at 22:02 UTC
    Move the declaration of @dirlist after the nested sub (getAns), then pass it in as a hard reference:
    sub getDirs() { sub getAns() { my ($dirlist) = @_; # new print qq(Enter a valid directory: ); chomp(my $ans = <STDIN>); if ($ans ne "") { if ($ans =~ m/foo/g) { push(@$dirlist, $ans); # note the @$dirlist &getAns; } else { print qq(That is not a valid directory!\n); &getAns; } } else { return @$dirlist; # note the @$dirlist } } my @dirlist; my @dirs = getAns(\@dirlist); # note the \@dirlist if (@dirs) { return @dirs; } else { die qq(No directories have been entered!\n); } }

    For more information on hard references, take a look at perlref.

    Just a stylistic note, you don't need to put the & on getAns to call if if you're already using () (the original has a line which read my @dirs = &getAns()). As a matter of fact, you should stay away from using & to call subroutines unless you understand how it's different from calling them with (). Calling with & makes @_ in the called subroutine an alias for @_ in the caller; () makes a copy instead. So changing the parameters in the subroutine could affect the variables used in the main program. This is probably not what you expect! Be careful. If I were you, I'd change the places in your code that call &getAns to getAns().

    Anyway, hope this helps.

Re: Where to declare?
by Rich36 (Chaplain) on Oct 24, 2001 at 22:25 UTC
    Thanks very much for your help. The "while" loop definitely simplified things.

    And this -
    As a matter of fact, you should stay away from using & to call subroutines unless you understand how it's different from calling them with (). Calling with & makes @_ in the called subroutine an alias for @_ in the caller; () makes a copy instead. So changing the parameters in the subroutine could affect the variables used in the main program. This is probably not what you expect! Be careful.
    - is definitely information I can use. I tend to be pretty liberal about using both "&" and "()" in my subroutine calls. I didn't realize there was a difference.

    Thanks for the help and enlightenment...
    Rich36

      Actually, that bit of text you quoted is incorrect. Using & without () does what is described. Using both together is probably a good practice, especially if you aren't in the habit of giving your subroutines names with mixed case. See (tye)Re: A question of style for more info.

              - tye (but my friends call me "Tye")

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (7)
As of 2021-05-14 11:25 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Perl 7 will be out ...





    Results (150 votes). Check out past polls.

    Notices?