Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

Perl variable scoping between functions

by Bryan882 (Novice)
on Jul 18, 2018 at 09:42 UTC ( [id://1218730]=perlquestion: print w/replies, xml ) Need Help??

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

Hello monks, I am somewhat confused at the behaviour of the code from within this perl script which I am trying to create. In short it is a function which will take a file specified at runtime and put it into a list. What you can see below is that I have it working from within the function but it doesn't seem to work correctly when i call it from another function and try to put it into an array etc.
sub fLoadModules { my ($modules) = @_; open my $fh, "<", $modules or die "Couldn't open module file: $mod +ules"; while(<$fh>) { chomp; my ($module_id) = split /;/; print Dumper($module_id); } close $fh; }
its also worth mentioning that $modules is declared in main, which will send the file path to this function above. The data will print within the sub but when called from another sub it runs into difficulty.

Replies are listed 'Best First'.
Re: Perl variable scoping between functions
by tobyink (Canon) on Jul 18, 2018 at 10:55 UTC

    I guess you want something like this…

    sub fLoadModules { my ($modules) = @_; my @stuff_to_return; open my $fh, "<", $modules or die "Couldn't open module file: $mod +ules"; while(<$fh>) { chomp; my ($module_id) = split /;/; print Dumper($module_id); push @stuff_to_return, $module_id; } close $fh; return @stuff_to_return; }
      True, you can always return an array but I have been unsuccessful thusfar in calling the sub containing the array. For clarity I have posted the way in which I attempt to call the sub.
      ##MAIN my $modules_path = $opts{e}; my $modules = fLoadModules $modules_path; sub Other { my @other = fLoadModules(); }
        The variable $modules declared in MAIN is shadowed by the lexical $modules declared inside the function. To properly pass parameters to @_, put them into the parameter list:
        my @other = fLoadModules($modules);

        @other will be empty, as fLoadModules doesn't return anything, but that's already been covered in other replies.

        ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
Re: Perl variable scoping between functions
by hippo (Bishop) on Jul 18, 2018 at 10:02 UTC
    it doesn't seem to work correctly ... it runs into difficulty

    These aren't really useful descriptions of the problem, sorry. Since you haven't shown how you are calling the sub, much less provided an SSCCE, it's pretty hard to help.

    Update: That said, your sub doesn't return anything, perhaps that's the problem? Without an SSCCE it's still just a guess however.

      Aha, That would be useful i guess. From another function I have been calling it this way. I am trying to put the file into an array which I can later make use of.
      my @retarr = fLoadModules($modules);

        Thanks. Your sub as written does not return anything so the @retarr array will be empty. You need to return a list like this:

        #!/usr/bin/env perl use strict; use warnings; use Data::Dumper; my @retarr = (); print "At init " . Dumper (\@retarr); @retarr = void (); print "After void " . Dumper (\@retarr); @retarr = getlist (); print "After getlist " . Dumper (\@retarr); exit; sub void { # doesn't return anything } sub getlist { return (0, 1, 2); }

        That is an SSCCE. See also return. HTH.

Re: Perl variable scoping between functions
by holli (Abbot) on Jul 18, 2018 at 13:52 UTC
    Naming is important. You are not naming your variable v_module_id, so don't name your functions fSomething.


    holli

    You can lead your users to water, but alas, you cannot drown them.
Re: Perl variable scoping between functions
by Bryan882 (Novice) on Jul 19, 2018 at 11:42 UTC
    For those who teased out the various pitfalls and solutions i thank you! I have solved it, my biggest pitfall was incorrectly passing data to the sub and trying to call the fLoadModules sub from another sub and main. As seen in the thread, indeed the most convenient way is to dump the data into an array and return it like so.
    sub fLoadModules { my ($modules) = @_; my @array; open my $fh, "<", $modules or die "Couldn't open module file: $mod +ules"; while(<$fh>) { chomp; my ($module_id) = split /;/; push @array, $module_id; } close $fh; return @array; }
    And in main() I have taken the argument via command line for the path to the folder containing the file needed.
    my $modules_path = $opts{e};
    Next I pass $module_path to the sub which will call the other sub (to retrieve the list from the file)
    fCompose $dbh, $modules_path;
    Finally from within that sub I can call fLoadModules to obtain the data I need.
    sub fCompose { my($dbh, $modules_path) = @_; my @retstr = fLoadModules($modules_path); .... }
    So for clarity, this was the issue and how it was rectified. Thank you once again to the contributors, it is as always a big help when its needed!

      This is why I asked "why are you calling the sub twice?"

      You appeared to be calling the sub once to pass arguments to it, then again (without passing any arguments) to retrieve the result. That's not how subs work.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others surveying the Monastery: (5)
As of 2024-04-19 06:52 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found