http://qs321.pair.com?node_id=193991

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

Replies are listed 'Best First'.
(jeffa) Re: Collecting all values with shift
by jeffa (Bishop) on Aug 30, 2002 at 04:07 UTC
    Best? smartest? A Perl hacker craves not these things ... wait, we do? A Perl hacker craves these things! ;)

    Personally, i opt for something like:

    sub foo { my ($bar,$baz,@qux) = @_; # yadda yadda yadda }
    and not bother with shifting individual values.

    UPDATE:
    blaze just /msg'ed me with a question (thanks blaze), so maybe i was not completely clear ... So, you don't know how many arguments you are going to deal with. You could always use a for loop like so:

    sub foo { print "$_\n" for @_; }
    Also, i accidently used $qux, in the first snippet when i meant @qux - erikharrison explains this much better than i can. Out of curiosity Samn, just exactly what are you trying to do?

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
      Just a quick appendum. Be careful to make a copy of @_ locally if you are manipulating things a bit, eg:
      #!/usr/bin/perl -w use strict; my @words = ('These','are','words',"\n"); print "Original: @words"; safesub(@words); print "After safe sub: @words"; unsafesub(@words); print "After unsafe sub: @words"; exit(0); sub safesub { print "safesub to uppercase: "; my @uppercasewords = @_; for (@uppercasewords) { tr/a-z/A-Z/; } print "@uppercasewords"; } sub unsafesub { print "unsafesub to uppercase: "; for (@_) { tr/a-z/A-Z/; } print "@_"; } # output Original: These are words safesub to uppercase: THESE ARE WORDS After safe sub: These are words unsafesub to uppercase: THESE ARE WORDS After unsafe sub: THESE ARE WORDS
      Notice how after unsafe sub has been called that @words has changed. If that's not what you're expecting, it can sometimes give you a shock. So unless the sub is very trivial, or you specifically do intend to amend the caller var(s), make sure you make a copy to play with in the sub.

      .02

      cLive ;-)

      --
      seek(JOB,$$LA,0);

Re: Collecting all values with shift
by erikharrison (Deacon) on Aug 30, 2002 at 04:27 UTC

    If you are not sure of the number of args, just assign to an array

    sub foo { my (@args) = @_; }

    Why not use @_ directly, you may ask? Well, first, @_ has magical powers. Second, it's less readable.

    In fact, ask yourself why the sub has a variable number of args - is it trying to do to much? If so, then maybe you ought to consider breaking the function down into smaller bits with more clearly defined purposes

    If the function has a clear need for multiple args, it may still be true that the first couple of args have a defined purpose and the remainder of the args define a variable length additional data. In that case, consider naming those important initial args in a useful way, leaving the remainder in a list.

    sub foo_which_processes_a_list { my ( $employee_name, @tasks) = @_; }

    This has the added benefit of promoting useful information out of the collection of the list to a more important looking scalar

    Cheers,
    Erik

    Light a man a fire, he's warm for a day. Catch a man on fire, and he's warm for the rest of his life. - Terry Pratchet

Re: Collecting all values with shift
by dws (Chancellor) on Aug 30, 2002 at 04:13 UTC
    What is the best and smartest way to get all values passed to a subroutine, when the number of incoming values is not known? while (shift) ?

    @_ holds all of the values passed.

    my @copy = @_; # gets you a copy, if that's what you need

Re: Collecting all values with shift
by screamingeagle (Curate) on Aug 30, 2002 at 04:52 UTC
    my suggestion would be to pass a reference to a hash to the subroutine; using this approach, u could pass any number of variables by just assigning a key => value to the hash, and since you're passing the hash by reference to the subroutine, you'll be able to access all the hash data inside the subroutine by simply dereferencing the hash. for example,
    my %myhash = (); $myhash{'key1'} = val1; $myhash{'key2'} = val2; testsub(\%myhash); sub testsub { my $reftohash = shift; print $reftohash->{'key1'}; print $reftohash->{'key2'}; }