Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Returning a list from a sub

by coec (Chaplain)
on Jul 24, 2002 at 02:33 UTC ( [id://184668]=perlquestion: print w/replies, xml ) Need Help??

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

Hi all

In the following sub, I want to return the list @List to the calling sub. How do I do this?

sub TSM_Enquire { my $Record, $Slot, $Type, $Label; my @List; open(IN,"adsm_cmd q libv|grep 3584|"); open(OUT,">/tmp/show_library.$$"); while ($Record = <IN>) { $Record =~ s/,//; @Fields = split(' ', $Record, 9999); $Lable = $Fields[$#Fields-1] $Slot = $Fields[2]; push(@List, $Slot . " " $Type . " " . $Lable); } close(IN); close(OUT); }
"adsm_cmd q libv|grep 3584" returns
<snip> 3584LIB1 922ABL Private Data 1,036 3584LIB1 923ABL Scratch 1,100 3584LIB1 924ABL Private Data 1,076 3584LIB1 925ABL Private Data 1,030 3584LIB1 926ABL Private Data 1,078 3584LIB1 938ABL Private Data 1,025 3584LIB1 939ABL Private Data 1,037 3584LIB1 CLNI88 Cleaner 1,026 3584LIB1 CLNI89 Cleaner 1,038 </snip>
To finish up, I want to return the list containing slot, type and label to the calling function and the the calling function needs to loop through the list and take various actions depneding on the slot range and type.
TIA
coec

Replies are listed 'Best First'.
Re: Returning a list from a sub
by VSarkiss (Monsignor) on Jul 24, 2002 at 03:00 UTC

    The return value of a sub in Perl is the value of the last expression, or you can explicitly use a return statement. In this case, since there's only path through the sub, you can just do:

    close(OUT); @List; }
    or to make things explicit:
    close(OUT); return @List; }
    Whichever you prefer.

    However, there are a couple of other improvements in your code which would make it simpler, easier, and more general.

    • Don't use the third argument to split unless you really need it. Perl will allocate space as needed.
    • To get the next-to-last element of the @Fields array, just use $Fields[-2].
    • You're only using $Record as a placeholder. That's just what $_ is meant for.
    Putting all these together, your loop becomes:
    while (<IN>) { s/,//; @Fields = split ' '; $Lable = $Fields[-2]; #sic -- should be "Label" $Slot = $Fields[2]; # You never set $Type, so the next line will get # a "use of undefined value" warning. push @List, "$Slot $Type $Lable"; } # You also never write anything to OUT

    HTH

Re: Returning a list from a sub
by zejames (Hermit) on Jul 24, 2002 at 03:34 UTC
    Hello

    Almost nothing to add to VSarkiss's excellent answer : It would be more perlish to select inside the loop lines containing "3584". Indeed, using a double pipe, you create a extra process for the grep. This solution avoids it :

    open(IN,"adsm_cmd q libv|"); open(OUT,">/tmp/show_library.$$"); while (<IN>) { next unless (/3584/); # VSarkiss stuff ... }

    HTH

    --
    zejames
      Thanks for the great advice.
      I'm still stuck, though, on how to loop through this list from the calling sub.
      sub TSM_Enquire { my $Slot, $Type, $Label; open(IN,"/bbs/rtscripts/adsm_cmd q libv|"); while (<IN>) { next unless (/3584/); s/,//; @Fields = split ' '; $Label = $Fields[2]; $Slot = $Fields[$#Fields-1]; $Type = $Fields[3]; push @List, "$Slot $Type $Label"; } close(IN); return @List; } sub Process_Columns { my $Count=0; my $Simple; my @Column_Info = ( [ 1024, 1067 ], # Column 1 start stop [ 1068, 1093 ], # Column 2 start stop [ 1094, 1137 ], # Column 3 start stop [ 1138, 1163 ], # Column 4 start stop [ 1164, 1207 ], # Column 5 start stop [ 1208, 1233 ], # Column 6 start stop [ 1234, 1277 ], # Column 7 start stop [ 1278, 1321 ] ); # Column 8 start stop if ($LibraryType =~ "tsm") { @List = TSM_Enquire; } else { @List = Tapeutil_Enquire; } for ($Count=1;$Count<=8;$Count++) { # Traverse columns my $StartPos = $Column_Info[$Count][1]; my $Pos = $StartPos; my $Column_Count = 0; my $EndPos = $Column_Info[$Count][2]; my $NewPos=0; my $NewLabel=""; my $NewRec=""; while ($NewRec = @List) { chomp $NewRec; $NewRec =~ s/^ //; ($Pos, $Type, $Label) = split(' ', $NewRec, 9999); for ($I=1;$I<=($EndPos-$StartPos)+1;$I++) { <snip>
      I that the above is wrong (because it doesn't work, read as: doesn't do what I want).
      Any ideas, comments, etc?
      TIA
      coec
        It looks suspiciously like you have a scoping issue with @List. What is probably happening is that you have (either explicitly or implicitly) created a *global* variable called @List, rather than a local variable within each subroutine. I would suggest adding my @List; to the beginning of your TSM_Enquire and Process_Columns subs, which will give them each a private copy of the list that is empty each time the sub is first executed. For more details, you can check out the sections on scoping in perldoc perlsub.

        Also, you might also want to use strict; at the beginning of your program to help catch errors like this in the future.

        If that doesn't solve the problem, it might be worth trying some simple debugging tricks, like adding warn statements on subroutine entry and exit and when you are manipulating @List or other variables that are central to what your code is trying to accomplish.

Re: Returning a list from a sub
by sauoq (Abbot) on Jul 24, 2002 at 03:56 UTC
    The split won't work like you might expect as the data in your fourth column seems to be optional. You'll probably want to use a regular expression.
    @Fields = /(\S*)\s+(\S*)\s+(\S*)(.*?)(\d.*)/;

    Besides the improvements to your loop already suggested by VSarkiss, you can use array slices and the fact that "@array" will separate the values using $" which defaults to " " (a space) to eliminate all those temp variables and concatenations.

    push @List, "@Fields[2,3,-1]"; # Fix the columns as necessary.

    Finally, I'd suggest you read up on references and consider returning a reference to the array instead of the whole list.

    -sauoq
    "My two cents aren't worth a dime.";
    

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others admiring the Monastery: (4)
As of 2024-04-25 08:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found