in reply to Re^6: perlsub question..
in thread perlsub question..

This is precisely the mental model of parameter passing, that I'm trying to develop. Not the @arry passing part - - That's fine - you pass a list.

Your statement :
      @bar expands to a list of its elements, with anonymous undefined values in place of nonexistent elements
is negated by the code I posted. If "nonexistent elements" were indeed passed, assigning values to the corresponding aliases would vivify, in the original array. This is not the case.

The only elements that can get persistent new values from inside the sub are "existing" elements, or explicitly passed elements, as Jenda indicated.

I agree that it would be crufty to take advantage of this in production code. I also think this behaviour is "correct", and sufficiently documented for most code, and can be persuaded that since the behaviour is subject to change, it should not be encouraged/documented. I'm just trying to understand what the behaviour is, and trying to ensure that I have not mis-understood it.

     "An undefined problem has an infinite number of solutions." - Robert A. Humphrey         "If you're not part of the solution, you're part of the precipitate." - Henry J. Tillman

Replies are listed 'Best First'.
Re^8: perlsub question..
by ysth (Canon) on Jun 24, 2007 at 21:49 UTC
    Your statement :
         
    @bar expands to a list of its elements, with anonymous undefined values in place of nonexistent elements
    is negated by the code I posted. If "nonexistent elements" were indeed passed, assigning values to the corresponding aliases would vivify, in the original array. This is not the case.
    You misunderstood me. I said nonexistent elements are not passed, and that anonymous (i.e. not bound to the array in any way) undefined values are passed in their place.
Re^8: perlsub question..
by shmem (Chancellor) on Jun 24, 2007 at 21:59 UTC
    Your statement :
    @bar expands to a list of its elements, with anonymous undefined values in place of nonexistent elements
    is negated by the code I posted.

    No, it's not. In that post you treated @_ as an array and created new elements in it

    sub x{ @_[3,4,5,6,8]=(3,4,5,6,939);show(@_)}
    and expected that the new elements find their place in the original array, @y. Doesn't work, no way it could. Let's dissect that.
    my @y;$y[3]=undef;

    The array @y now has 4 elements, as perl -le 'my @y;$y[3]=undef;print scalar @y' confirms.

    x(@y);

    Now that is exactly the same as saying

    x($y[0],$y[1],$y[2],$y[3]);

    Then, in function x() you do

    @_[3,4,5,6,8]=(3,4,5,6,939);

    Are you expanding the parameter list after the fact of the subroutine call, or assigning to a different array? What do the docs say to that?

    Any arguments passed in show up in the array @_. Therefore, if you called a function with two arguments, those would be stored in $_[0] and $_1. The array @_ is a local array, but its elements are aliases for the actual scalar parameters. In particular, if an element $_[0] is updated, the corresponding argument is updated (or an error occurs if it is not updatable). If an argument is an array or hash element which did not exist when the function was called, that element is created only when (and if) it is modified or a reference to it is taken. (Some earlier versions of Perl created the element whether or not the element was assigned to.) Assigning to the whole array @_ removes that aliasing, and does not update any arguments.

    (emphasis mine) - assigning to the array slice @_ is also assigning to the array @_, it's just a special form.

    Doing that you break the aliasing, and the elements you passed in (the elements of @y) stay as they were.

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
      x(@y) is not exactly the same as saying x($y[0], $y[1], ...). It differs when one of the elements does not exist. That's the point of this subthread.

      And the documentation you cite does not apply; assigning to an array slice is not assigning to the array and does not remove the aliasing.

      Try it.

        Try it.

        I do and see

        #!/usr/bin/perl use strict; use warnings; use Data::Dump::Streamer; sub x { print "\@_ number of elements: ", scalar(@_),"\n"; ($_[0],$_[2]) = qw(foo bar); @_[3,4,5,6,8] = (3,4,5,6,939); bar(@_); } sub bar { print 'bar @_=(',join(',',map{"'$_'"} @_),")\n"; $_[3] = 'quux'; } my @y; $y[3] = undef; x(@y); Dump(\@y); __END__ @_ number of elements: 4 bar @_=('foo','','bar','3','4','5','6','','939') $ARRAY1 = [ ( undef ) x 3, 'quux' ];

        that you are right. Assigning to ($_[0],$_[2]) has effect to @_, but there are no aliases to something in @y.

        --shmem

        _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                      /\_¯/(q    /
        ----------------------------  \__(m.====·.(_("always off the crowd"))."·
        ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}