@_ in subroutine corrupts data?

Ask a Question related to PERL Miscellaneous, Design and Development.

  1. #1

    Default @_ in subroutine corrupts data?

    hello --

    I can find no reasonable explanation for this behavior. Not theat
    there's isn't one (a trivial one at that), but I am having a hard time
    finding the reason for this:

    #!/usr/bin/perl

    @array = subthis(1, 2, 3, 4);

    sub subthis {

    @array = @_;
    foreach (@array) {
    print "$array[$_]\n";
    }
    return (@array);
    }

    print "Finished\n";

    $ perl subrout2.pl
    2
    3
    4

    Finished


    Whatever happened to the "1"?
    Is this behavior to be expected? Why?
    I get the same response in Perl 5.6 and 5.8

    TIA

    Henry

    synthespian Guest

  2. Similar Questions and Discussions

    1. Contribute 3 corrupts filenames
      After several years mixing and matching DreamWeaver and FrontPage, I am keen to get all my authors off of FrontPage (which we get FOC) - I can't...
    2. Director Corrupts Display
      Has anyone else had this problem, when I'm working Director 8.5.1 and have the vector shape window and working on a vector, suddenly the vector image...
    3. move_uploaded_file() corrupts some files
      The move_uploaded_file() function is very quirky. I want to allow users to upload images to the Web site. Here is the code: ...
    4. form corrupts when sorted
      I have a master form that uses tab controls. There are 7 tabs which are attached to subforms When I sort the first subform by the last column...
    5. DWMX corrupts file
      I have a .cfm file with the following lines: </td> </cfloop> </tr> </cfloop> When I open the file in DWMX it changes to: </td> </tr></cfloop>
  3. #2

    Default Re: @_ in subroutine corrupts data?

    In article <bkb5d9$p90ge$1@ID-78052.news.uni-berlin.de>, synthespian wrote:
    > I can find no reasonable explanation for this behavior. Not theat
    > there's isn't one (a trivial one at that), but I am having a hard time
    > finding the reason for this:
    >
    > #!/usr/bin/perl
    >
    > @array = subthis(1, 2, 3, 4);
    >
    > sub subthis {
    >
    > @array = @_;
    > foreach (@array) {
    > print "$array[$_]\n";
    > }
    > return (@array);
    > }
    >
    > print "Finished\n";
    >
    > $ perl subrout2.pl
    > 2
    > 3
    > 4
    >
    > Finished
    >
    > Whatever happened to the "1"?
    You are looping through the values in @array, and then indexing the array
    based on those values. In other words, this is what you're printing:

    $array[1]
    $array[2]
    $array[3]
    $array[4]

    Since arrays are 0-indexed, you are getting three values and an undefined
    fourth value. I think what you meant to say was:

    print "$_\n";

    Instead of:

    print "$array[$_]\n";

    Dave

    --
    ..:[ dave benjamin (ramenboy) -:- [url]www.ramenfest.com[/url] -:- [url]www.3dex.com[/url] ]:.
    : d r i n k i n g l i f e o u t o f t h e c o n t a i n e r :
    Dave Benjamin Guest

  4. #3

    Default Re: @_ in subroutine corrupts data?

    On Wed, 17 Sep 2003 23:28:39 -0300, synthespian <synthespian@uol.com.br> wrote:
    > hello --
    >
    > I can find no reasonable explanation for this behavior. Not theat
    > there's isn't one (a trivial one at that), but I am having a hard time
    > finding the reason for this:
    >
    > #!/usr/bin/perl
    you are missing use strict; and use warnings; (or -w).
    >
    > @array = subthis(1, 2, 3, 4);
    >
    > sub subthis {
    >
    > @array = @_;
    > foreach (@array) {
    That will set $_ to 1, then 2, then 3, then 4.
    > print "$array[$_]\n";
    Since arrays start at element 0 (well, in sane code anyway) that will
    print the second element when $_ is 1, the third when $_ is 2, the
    fourth when $_ is 3, and the fifth when $_ is 4.
    > }
    > return (@array);
    > }
    >
    > print "Finished\n";
    >
    > $ perl subrout2.pl
    > 2
    > 3
    > 4
    >
    Notice the blank line, that's $array[4] which is undef.
    > Finished
    >
    >
    > Whatever happened to the "1"?
    You didn't print it.
    > Is this behavior to be expected? Why?
    Yes. Values aren't the same an indexes.

    --
    Sam Holden

    Sam Holden Guest

  5. #4

    Default Re: @_ in subroutine corrupts data?

    "synthespian" <synthespian@uol.com.br> wrote in message
    news:bkb5d9$p90ge$1@ID-78052.news.uni-berlin.de...
    > #!/usr/bin/perl
    >
    > @array = subthis(1, 2, 3, 4);
    >
    > sub subthis {
    >
    > @array = @_;
    > foreach (@array) {
    On each iteration $_ contains an actual element of the array, not just the
    index.
    > print "$array[$_]\n";
    This should be written: print "$_\n";

    As it is, you're using the item to do a look-up on the array. You've
    already got this via foreach. The fact that you're getting anything close
    to a correct output is...
    > }
    > return (@array);
    > }
    >
    > print "Finished\n";
    >
    > $ perl subrout2.pl
    > 2
    > 3
    > 4
    .... that the items in the array are (for the most part) valid indices for
    that array, except that arrays in Perl begin with index zero, and your array
    doesn't contain zero.

    Also, by using @array in the "main" scope of your program, and inside the
    "subthis" subroutine, your "@array = @_" line is always going to overwrite
    the @array in the main scope.

    The following does not have this problem.

    #!/usr/bin/perl

    @array = subthis(1, 2, 3, 4);

    sub subthis {
    my @array = @_;
    foreach my $item (@array) {
    print "$item\n";
    }
    return @array;
    }




    ---
    Outgoing mail is certified Virus Free.
    Checked by AVG anti-virus system ([url]http://www.grisoft.com[/url]).
    Version: 6.0.512 / Virus Database: 309 - Release Date: 8/19/2003


    Chris Dutton Guest

  6. #5

    Default Re: @_ in subroutine corrupts data?

    Sam Holden wrote:
    > On Wed, 17 Sep 2003 23:28:39 -0300, synthespian <synthespian@uol.com.br> wrote:
    >
    >>hello --
    >>
    >> I can find no reasonable explanation for this behavior. Not theat
    >>there's isn't one (a trivial one at that), but I am having a hard time
    >>finding the reason for this:
    >>
    >>#!/usr/bin/perl
    >
    >
    > you are missing use strict; and use warnings; (or -w).
    >
    >
    >>@array = subthis(1, 2, 3, 4);
    >>
    >>sub subthis {
    >>
    >> @array = @_;
    >> foreach (@array) {
    >
    >
    > That will set $_ to 1, then 2, then 3, then 4.
    >
    >
    >> print "$array[$_]\n";
    >
    >
    > Since arrays start at element 0 (well, in sane code anyway) that will
    > print the second element when $_ is 1, the third when $_ is 2, the
    > fourth when $_ is 3, and the fifth when $_ is 4.
    >
    Yes, it's obvious! Thanks to you and Chris Dutton for taking the time.
    I thought that what would be set to $_ was the /number/ of elements in
    @array, and not 1, 2, 3, 4, and that this number would start at 0.
    Like Dave said, "Since arrays are 0-indexed, you are getting three
    values and an undefined
    fourth value. I think what you meant to say was:
    print "$_\n";
    Instead of:
    print "$array[$_]\n";

    So this is about context, is it? $_ will be the placeholder for an
    array indexed when $array[$_], otherwise it is not 0-indexed, that is,
    is $_ in the case of print "$_\n" evaluating to the number of elements?
    Or is it a placeholder for the /elements/ themselves?
    What's up with this (perceived) inconsistency?

    Thanks for answering.

    Regs,

    Henry

    synthespian Guest

  7. #6

    Default package problem? [was Re: @_ in subroutine corrupts data?]

    While we're on this, it got weird with "strict" and "warnings". Why?


    @arrayb = subthat(1, 2, 3, 4);

    sub subthat {
    @arrayb = @_;
    foreach (@arrayb) {
    print "$_\n";
    }
    }

    print "Finished\n";

    $ perl subrout3.pl
    Global symbol "@arrayb" requires explicit package name at subrout3.pl
    line 5.
    Global symbol "@arrayb" requires explicit package name at subrout3.pl
    line 9.
    Global symbol "@arrayb" requires explicit package name at subrout3.pl
    line 10.
    Execution of subrout3.pl aborted due to compilation errors.

    TIA
    Henry

    synthespian Guest

  8. #7

    Default Re: package problem? [was Re: @_ in subroutine corrupts data?]

    On Thu, 18 Sep 2003 00:41:30 -0300, synthespian <synthespian@uol.com.br> wrote:
    > While we're on this, it got weird with "strict" and "warnings". Why?
    perldoc strict
    >
    >
    > @arrayb = subthat(1, 2, 3, 4);
    >
    > sub subthat {
    > @arrayb = @_;
    > foreach (@arrayb) {
    > print "$_\n";
    > }
    > }
    >
    > print "Finished\n";
    >
    > $ perl subrout3.pl
    > Global symbol "@arrayb" requires explicit package name at subrout3.pl
    > line 5.
    > Global symbol "@arrayb" requires explicit package name at subrout3.pl
    > line 9.
    > Global symbol "@arrayb" requires explicit package name at subrout3.pl
    > line 10.
    > Execution of subrout3.pl aborted due to compilation errors.

    The section marked "strict vars" is the relevant bit.

    --
    Sam Holden

    Sam Holden Guest

  9. #8

    Default Re: @_ in subroutine corrupts data?

    * synthespian <synthespian@uol.com.br>:


    [...]
    > So this is about context, is it? $_ will be the placeholder for an
    > array indexed when $array[$_], otherwise it is not 0-indexed, that is,
    > is $_ in the case of print "$_\n" evaluating to the number of
    > elements? Or is it a placeholder for the /elements/ themselves?
    > What's up with this (perceived) inconsistency?
    There's no inconsistency. In a loop such as:

    foreach (@array) {
    ...
    }

    $_ is set to each element of the array in turn. At no point does $_
    contain an array index or the array size except by mathematical
    coincidence (that is, the numbers happen to be the same).

    The following code should illustrate the point (yes, it's mostly your
    code, I just tweaked what it prints and declared some variables and give
    it different input):

    #!/usr/bin/perl
    my @words = subthis( "hello", "xyzzy", "plugh" );

    sub subthis {
    my @array = @_;
    foreach (@array) {
    print "$_\n";
    }
    return @array;
    }



    cheers,
    --
    Iain.
    Iain Truskett Guest

  10. #9

    Default Re: package problem? [was Re: @_ in subroutine corrupts data?]

    "synthespian" <synthespian@uol.com.br> wrote in message
    news:bkb9kv$qum8m$1@ID-78052.news.uni-berlin.de...
    > While we're on this, it got weird with "strict" and "warnings". Why?
    >
    >
    > @arrayb = subthat(1, 2, 3, 4);
    >
    > sub subthat {
    > @arrayb = @_;
    > foreach (@arrayb) {
    > print "$_\n";
    > }
    > }
    >
    > print "Finished\n";
    >
    > $ perl subrout3.pl
    > Global symbol "@arrayb" requires explicit package name at subrout3.pl
    > line 5.
    As I mentioned in my earlier reply, when you assign to @arrayb in your
    subroutine, you're not automatically creating a new array. Rather you're
    assigning to the @arrayb that's already in the "main" package. Now, while
    you can do this, it's not advisable since you can get unexpected results.

    You can use the "my" keyword to create a new array inside the subroutine
    which has the same name as one in the outer scope.

    @arrayb = subthat(1, 2, 3, 4);

    sub subthat {
    my @arrayb = @_;
    foreach (@arrayb) {
    print "$_\n";
    }
    # and I presume from your previous subroutine,
    # and how this one is used, that you want @arrayb
    # returned.
    return @arrayb;
    }





    ---
    Outgoing mail is certified Virus Free.
    Checked by AVG anti-virus system ([url]http://www.grisoft.com[/url]).
    Version: 6.0.512 / Virus Database: 309 - Release Date: 8/19/2003


    Chris Dutton Guest

  11. #10

    Default Re: @_ in subroutine corrupts data?

    "synthespian" <synthespian@uol.com.br> wrote in message
    news:bkb8j5$rjcqj$1@ID-78052.news.uni-berlin.de...
    > Yes, it's obvious! Thanks to you and Chris Dutton for taking the time.
    > I thought that what would be set to $_ was the /number/ of elements in
    > @array, and not 1, 2, 3, 4, and that this number would start at 0.
    To get the number of elements in an array, assign it to a scalar, like so:

    my @someArray = (1,2,3,4);
    my $lengthOfArray = @someArray;
    print "$lengthOfArray\n";
    # prints:
    # 4
    > So this is about context, is it? $_ will be the placeholder for an
    > array indexed when $array[$_], otherwise it is not 0-indexed, that is,
    > is $_ in the case of print "$_\n" evaluating to the number of elements?
    > Or is it a placeholder for the /elements/ themselves?
    $_ is just a helpful timesaver. It can be a shortcut in that many of Perl's
    built-ins use it if no argument is provided. For instance, "print;" is
    equivalent to "print $_;".

    In the foreach loop, $_ serves as a shortcut to each element of the array.
    This can be easily replaced with a more meaningful name if your goal is
    long-term maintainability.

    foreach (@foo) { print }

    is equivalent to:

    foreach my $item (@foo) { print $item }


    ---
    Outgoing mail is certified Virus Free.
    Checked by AVG anti-virus system ([url]http://www.grisoft.com[/url]).
    Version: 6.0.512 / Virus Database: 309 - Release Date: 8/19/2003


    Chris Dutton Guest

  12. #11

    Default Re: @_ in subroutine corrupts data?

    synthespian <synthespian@uol.com.br> wrote:
    > Sam Holden wrote:
    >> On Wed, 17 Sep 2003 23:28:39 -0300, synthespian <synthespian@uol.com.br> wrote:
    >>
    >>> I can find no reasonable explanation for this behavior.

    See the "Foreach Loops" section in perlsyn.pod.

    >>>@array = subthis(1, 2, 3, 4);
    >>>
    >>>sub subthis {
    >>>
    >>> @array = @_;
    >>> foreach (@array) {
    >>
    >>
    >> That will set $_ to 1, then 2, then 3, then 4.
    >>
    >>
    >>> print "$array[$_]\n";
    >>
    >>
    >> Since arrays start at element 0 (well, in sane code anyway) that will
    >> print the second element when $_ is 1, the third when $_ is 2, the
    >> fourth when $_ is 3, and the fifth when $_ is 4.
    >>
    >
    > Yes, it's obvious!
    > So this is about context, is it?

    If you mean list context vs. scalar context, then no, this
    is not about context.

    This is about how foreach loops work in Perl.

    > $_ will be the placeholder for an
    > array indexed when $array[$_], otherwise it is not 0-indexed, that is,

    You can manipulate lists using foreach without any explicit
    indexing at all.

    > is $_ in the case of print "$_\n" evaluating to the number of elements?
    > Or is it a placeholder for the /elements/ themselves?

    The correct term is "alias" rather than "placeholder".

    > What's up with this (perceived) inconsistency?

    It sounds like you haven't read up on the operation of foreach.


    --
    Tad McClellan SGML consulting
    [email]tadmc@augustmail.com[/email] Perl programming
    Fort Worth, Texas
    Tad McClellan Guest

  13. #12

    Default Re: package problem? [was Re: @_ in subroutine corrupts data?]

    synthespian <synthespian@uol.com.br> wrote:
    > While we're on this, it got weird with "strict" and "warnings". Why?

    use warnings has nothing to do with it, there are no warning
    messages below.

    > @arrayb = subthat(1, 2, 3, 4);
    > $ perl subrout3.pl
    > Global symbol "@arrayb" requires explicit package name at subrout3.pl
    > line 5.

    When you put "use strict" in your program, you are making this
    promise to perl:

    I will declare all of my variables before I use them.

    If you break your promise, perl will refuse to run your program.

    You are using @arrayb without declaring it, you've broken your promise.

    So, either declare the variable:

    my @arrayb = subthat(1, 2, 3, 4);

    or use an explicit package name:

    @main::arrayb = subthat(1, 2, 3, 4);


    --
    Tad McClellan SGML consulting
    [email]tadmc@augustmail.com[/email] Perl programming
    Fort Worth, Texas
    Tad McClellan Guest

Posting Permissions

  • You may not post new threads
  • You may post replies
  • You may not post attachments
  • You may not edit your posts

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139