http://www.perlmonks.org?node_id=107004

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

In my brand spanking new module, I'm trying to read in three arguments with what I thought was a standard trick of using shift
sub encode_string ($$$) {
    my ($reg, $ass, $check) = @_;
    return join $Delimiter, $reg, $ass, $check;
}
populates all three scalars, but
my ($reg, $ass, $check) = shift;
only populates the first one and the other two are undef. Why? Is this something to do with having the sub in a module and me shifting on the wrong list?

Replies are listed 'Best First'.
Re: shifting arguments
by ozone (Friar) on Aug 22, 2001 at 20:02 UTC
    from the perlfunc man page:
    "shift: Shifts the first value of the array off and returns it"

    shift only retrieves the first value from the array... so the other two would naturally be undef.

    you could do:

    my($reg, $ass, $check) = (shift, shift, shift);
    or try something clever with 'splice'
Re: shifting arguments
by MZSanford (Curate) on Aug 22, 2001 at 20:04 UTC
    Stirctly speaking, shift() can be used on any array to remove the top (0th) element and return it. But, shift() defaults to @_ if no array is supplied. Since shift is removeing and returning only the first (0th) element, assigning it's return to and array does not work. But, since Perl always tries it's hardest, it take the one value from the right (the return from shift) and assigns it to the first element on the left. Then, when there is no second value, it simply assigns undef to the folloing vars. Thats the simple version, without getting into stacks and such
    can't sleep clowns will eat me
    -- MZSanford
      Well and good, but I swear blind (maybe just myopic) that, when called in a list context, shift would depopulate @_ faster than Jimmy-Crack-Corn. Perhaps it only populates @list that way and not ($a, $b, $c).

      I'm off to do some experiments
      <sound of rustling pages and rummaging through dusty tomes>

Re: shifting arguments
by dga (Hermit) on Aug 22, 2001 at 20:41 UTC

    For multiple argument assignment I think the first example is clearer

    ($foo, $bar, $baz)=@_;

    My \$.02

Re: shifting arguments
by damian1301 (Curate) on Aug 22, 2001 at 21:34 UTC
    Just to note with what you are doing in that example, it would be much easier to just do something like:

    sub encode_string($$$){ return join $delimiter,@_; }


    $_.=($=+(6<<1));print(chr(my$a=$_));$^H=$_+$_;$_=$^H; print chr($_-39); # Easy but its ok.
      Of course, the question arises of how you're getting $delimiter ...

      ------
      /me wants to be the brightest bulb in the chandelier!

      Vote paco for President!

        $delimiter happens to be a global variable that is shared between 2 subs (could be anything the user desires, but needs to be consistant)