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

Hello. I'm new to this site, and Perl in general. I'm currently taking my first Perl course, and I'm having some trouble. Here is my problem...

I'm trying to pass an array to a subroutine, and from my understanding...all the arguments get passed to the subroutine in the array @_ , so what I'm trying to understand here, is if my original array get placed into another array, how can I pull that array out.

The "minimum" and "maximum" subroutines are different, because I've been trying different things with each one to get them to work, to no avail. I'm really at a loss here. I've looked through all my notes, my "Programming Perl" book (3rd edition), and also emailed the instructor. It seems like no matter what variations I try, I cannot get the subroutines to work. Any help would be greatly appreciated. Thank you.

  • Comment on Passing an array to a subroutine help?!

Replies are listed 'Best First'.
Re: Passing an array to a subroutine help?!
by jwkrahn (Abbot) on Mar 15, 2011 at 20:33 UTC
    if ($val != "0")

    You are using a numerical comparison on a text value which means that Perl has to convert the text values to numbers.    Normally Perl will make the correct conversion but this may cause problems.



    @values=(@values,$val);

    That is usually written as:

    push @values, $val;


    &maximum(@values,$arraysize); ... sub average { @stuff = @_; my $sum = 0; ($sum+=$_) for @stuff; my $average = $sum / $arraysize; return $average; }

    It looks like you meant average instead of maximum here?    You are passing $arraysize as well as @values to this subroutine which means that @_ inside the subroutine will have one more value than the numbers you want to calculate the average for.    You could simply remove that value using pop but there is no reason to pass the value in the first place as @_ would then have the same number of elements as @values and using @_ in scalar context would result in the same value as using @values in scalar context.

Re: Passing an array to a subroutine help?!
by wind (Priest) on Mar 15, 2011 at 20:03 UTC
    You're code is mostly fine, but you need to capture the results returned by your subroutines.
    my $min = minimum(@values); my $max = maximum(@values); my $average = average(@values);
    Also, you really should use strict to avoid unintended errors that perl will help you find.

      I'm not exactly sure what you mean. Sorry for being a pain, but what does  my $min = minimum(@values); do exactly? I really want to understand exactly how everything works. I also should've mentioned that the calculations must be performed by the subroutines for the assignment. I say this because I'm not sure what you meant, and I don't know if the first three lines of code you posted are doing the calculations or not. Thank you so much for your reply though! This has been driving me insane.

        Each of your subroutines returns a value. You must capture this returned value if you want to display the results in the following print statement.

        Here is your code with the small additions pointed out above

        use strict; print "\n\nEnter numbers, one number per line.\nEnter a blank line whe +n all values have been entered.\n"; my @values = (); while (my $val = <>) { chomp($val); if ($val != "0") { @values = (@values, $val); } elsif ($val eq "0") { print "Please do not enter values of zero.\n"; } elsif ($val eq "") { last; } } my $arraysize = @values; print "\nYou have entered $arraysize values\n\n"; my $min = minimum(@values); my $max = maximum(@values); my $average = average(@values); print "The minimum you have entered is $min\n\n"; print "The maximum you have entered is $max\n\n"; print "The average of the numbers you entered is $average\n\n"; sub maximum { my @args = @_; my $max = $args[0]; foreach my $i (@args) { if ($i > $max) { $max = $i; } } return $max; } sub minimum { my @things = @_; my $min = $things[0]; foreach my $z (@things) { if ($z < $min) { $min = $z; } } return $min; } sub average { my @stuff = @_; my $sum = 0; ($sum += $_) for @stuff; my $average = $sum / @stuff; return $average; }

        Note: Code run through Perl::Tidy to clean up the formatting

        Thank you again for your replies. My code now looks as follows...and works...

        print "\n\nEnter numbers, one number per line.\nEnter a blank line whe +n all values have been entered.\n"; my @values=(); while ($val=<>) { chomp($val); if ($val != "0") { @values=(@values,$val); } elsif ($val eq "0") { print "Please do not enter values of zero.\n"; } elsif ($val eq "") { last; } } my $arraysize=@values; print "\nYou have entered $arraysize values\n\n"; # &minimum(@values); # &maximum(@values); # &maximum(@values,$arraysize); my $min = minimum(@values); my $max = maximum(@values); my $average = average(@values); print "The minimum you have entered is $min\n\n"; print "The maximum you have entered is $max\n\n"; print "The average of the numbers you entered is $average\n\n"; sub maximum { @args = @_; my $max = $args[0]; foreach $i (@args) { if ($i > $max) { $max = $i; } } return $max; } sub minimum { my @things = @_; my $min = $things[0]; foreach my $z (@things) { if ($z < $min) { $min = $z; } } return $min; } sub average { @stuff = @_; my $sum = 0; ($sum+=$_) for @values; my $average = $sum / $arraysize; return $average; }

        I'm elated that it works now, but I'm still not quite understanding how part of it works (which is just as important to me as having it work). We were taught in class to call subroutines by the method I have shown above which is commented out. I'm especially confused by this, because for the "Average" subroutine, I figured I would need to pass "@values" as well as "$arraysize" for it to work, but it seems to work without "$arraysize". $arraysize isn't a global variable in the program because I used  my $arraysize, right? So how can the subroutine still work without passing it to that?

        I feel like there's some simple concept here that I am just not able to grasp or something, and it's extremely aggravating.

        Another question I have now, is if the subroutines return $min $max $average, why do I need those three lines

        my $min = minimum(@values); my $max = maximum(@values); my $average = average(@values);
        that set those variables to something again? Shouldn't they just work in the print statements after they're returned from the subroutines?

Re: Passing an array to a subroutine help?!
by kennethk (Abbot) on Mar 15, 2011 at 20:23 UTC
    If you need to pass multiple arrays to a subroutine, you need to use array references - see perlref, perlretut, perllol and/or perldsc. It might look something like:

    #!/usr/bin/perl use strict; use warnings; my @arrays = ( [1,2,3], [6,32,6,87], [2,456,56,7,3324,6,4365], ); iterator(@arrays); sub iterator { for my $array_ref (@_) { my $avg = average(@$array_ref); print "Your average is $avg\n" } } sub average { my @stuff = @_; my $sum = 0; ($sum+=$_) for @stuff; my $average = $sum / @_; return $average; }
Re: Passing an array to a subroutine help?!
by Douglas0028 (Novice) on Mar 15, 2011 at 21:35 UTC

    Thank you everyone so much for your replies! I think I have a better understanding of how subroutines work and the scope of variables as well. Programming is very difficult for me, hence why I am a networking major, heh. I'm sure I'll end up posting again on here at some point, but it's refreshing to know that there are people such as yourselves who're willing to help others, and to explain the way things work. Thank you all again.

    ~Douglas

      Programming is an acquired taste.   The very first program that I ever wrote ... was 8 lines long (in BASIC) ... took me six months to write ... and had a bug in it.   It is just what you know at the time, and what does or does not interest you.   Personally, I abhor dealing with anything having to do with “the hardware,” and that definitely includes “networking.”   I say that (in a good-natured way, of course...) because I have discovered that I am not particularly good at resolving hardware issues and that I have no patience for it.   To each his/her own.