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

hi i just a new be to perl and i trying to put mycode into subroutines and i having trouble passing two arrays and threre scalars to a subroutine i no it prob something simple.. heres my code:
use CGI qw(:standard); use CGI::Carp qw(fatalsToBrowser); use Socket; use Net::SNMP; use GD::Graph::lines; #function to print out a graph to screen using gd::graph sub print_graph#prints the graph to screen { my $q = new CGI; my ($xarray,$values,$xlabel,$ylabel,$title) = shift(@_); my @data = ($xarray,$values); my $graph = new GD::Graph::lines(500,350); $graph->set ( x_label => $xlabel, y_label => $ylabel, title => $title, x_label_skip => 'auto', y_label_skip => 'auto', line_width => 1, y_tick_number => 8, x_labels_vertical => 1, x_label_position => 1/2, transparent => 0, ); my $gd_image = $graph->plot(\@data); print $q->header(-type => "image/png"); binmode STDOUT; print $gd_image->png; } my $graphxlabel = "Time"; my $graphylabel = "No. Of Packets Recieved"; my $graphtitle = "No. Of Packets Recieved On Interface"; #function call print_graph(\@x_axis_array,\@values_array,\$grap +hxlabel,\$graphylabel,\$graphtitle);
where the two arrays @x_axis_array and @values_array have been previously filled in a while loop this code had been working before i tried to put it in a while loop so i no that the values are been filled into the arrays properly.. tanx in advance tommycahir

Replies are listed 'Best First'.
Re: passing multiple items to a subroutine
by Grygonos (Chaplain) on Mar 08, 2004 at 13:52 UTC

    Welcome to the monastery. When passing multiple non-scalar variables into a sub the arguement list gets flattened into a scalar list. This is why you must use references. perlref should be a good starting place to learn about references. FYI when returning values from a sub, the same rules apply. i.e. a sub that you needed to pass two arrays and a hash to would look like this.

    myMultipleArgSub(\@first,\@second,\%third);
    Forgive my previous answer. You do not need to use the shift function in conjuction with assigning the argument list. shift with out any arguments will take the first element off of the @_ array and return it as a scalar. The code  my ($xarray,$values,$xlabel,$ylabel,$title) = shift(@_); does not do what you expect. Two ways of doing it are
    my $xarray = shift; my $xarray = shift; my $values = shift; my $xlabel = shift; my $ylabel = shift; my $title = shift;
    This is really a bad way of getting this done...for that.. God gave us this method my ($xarray,$values,$xlabel,$ylabel,$title) = @_; This puts your scalars in list context and assigns the @_ list to it matching indexes to the order of the decalared variables. This is a good general purpose way to get this done.

    The code my @data = ($xarray,$values); probably doesn't do what you expect either. This will assign two array refs (assuming these are array refs) to @data if you want to assign the values of those arrays to @data you could
    push @data,$_ for @{$xarray}; push @data,$_ for @{$values};
    Not trying to nit pick at all .. but just trying to point out something that may not be what you had intended.
    After delving a little more into GD::Graph documentation I see you are doing what it expects here. Also drop
    use strict; use warnings;
    in the top of your script. For me its a good bonehead error catcher. Alot of the silly things we do get caught by those two pragma. Hope some of that was useful... again sorry for previous answer.

    Grygonos
      tanx Grygonos
      your ans was exactly what done the trick.. i only been programming perl for bout a month now so i going to leave the two pragma there for another while anyways until i get more confident in my own programming..
      my @data = ($xarray,$values);
      the @data expects a reference to two arrays
      as i said at the start i just an amatuer in the land of perl so forgive the stupid ques tanx tommycahir
        I wouldn't ever take them out... it doesn't hurt to have them in. It doesn't make your program any slower or less efficient. It's not a newbie thing to do by any means... when you start using strict and getting it right, then you know you are on the right path.

        Grygonos
Re: passing multiple items to a subroutine
by Crian (Curate) on Mar 08, 2004 at 13:44 UTC
    If you have to give more then one array to a subroutine, you have to use references.
    my @array1 = (0..9); my @array2 = ('a'..'l'); f(\@array1, \@array2);


    Update: In your function you can access the arrays via the references (and change the original Arrays, or you copy them to local arrays, if you dislike the references...

    sub f { my $aref1 = shift; my $aref2 = shift; print "$_\n" for @$aref1; ... }


    or

    sub f { my @a1 = @{shift}; my @a2 = @{shift}; print "$_\n" for @a1; ... }
      you have to use references

      That's what the OP is doing.

      The error is that (s)he is mixing shift and @_ inside the sub.

      A reply falls below the community's threshold of quality. You may see it by logging in.
Re: passing multiple items to a subroutine
by Hena (Friar) on Mar 08, 2004 at 14:02 UTC
    Other way would be using prototypes. In this case you should write it like this.
    # instead of # sub print_graph # try this sub print_graph (\@\@$$)
    This also helps, to make sure your calls to this subroutine are correct. Also your scalars would come as scalars to get them as references add '\' infront of '$'.