Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

Arrays: Last-index special variable vs. scalar values

by mwp (Hermit)
on Nov 16, 2000 at 00:17 UTC ( [id://41862]=perlquestion: print w/replies, xml ) Need Help??

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

$#array vs. @array

Simple question, simple answer, right? Well, maybe not. I was rambling along in the chatterbox this afternoon and said something that caused me to pause. After chewing my bottom lip for a moment I put together a test script and verified that I was wrong. But then I checked the perldocs and verified I was right. Now I'm just confused!

For a long time I have "known" that $#array returns the index of the last element in @array. From perlman:perldata:

  The length of an array is a scalar value. You may find the length of array @days by evaluating $#days, as in csh. (Actually, it's not the length of the array, it's the subscript of the last element, because there is (ordinarily) a 0th element.)

So far, so good. Essentially what I yammered into the chatterbox was something along the lines of: Beware the distinction between scalar @array and $#array. The former will return the number of elements in the list, while the latter will tell you the index of the last element. For example, if you have two lists (0..5) and (1,3,5) the special variable will return 5 in both instances, while the scalar values are 6 and 3, respectively. This is what caused me to double check myself by putting together a quick program:

#!/usr/bin/perl -w use strict; my @ary1 = (0..5); my @ary2 = (1,3,5); print scalar(@ary1), " ", scalar(@ary2), "\n";
print $#ary1, " ", $#ary2, "\n";

Which returns the following:

alakaboo:~$ ./test.pl 6 3 5 2

"Good, just as I... WAIT A MINUTE!" Imagine my surprise. That two should be a five! From perlman:perldata again, less than a page from the first pasting:

  If you evaluate a named array in a scalar context, it returns the length of the array. (Note that this is not true of lists, which return the last value, like the C comma operator, nor of built-in functions, which return whatever they feel like returning.) The following is always true: scalar(@whatever) == $#whatever - $[ + 1; Version 5 of Perl changed the semantics of $[: files that don't set the value of $[ no longer need to worry about whether another file changed its value. (In other words, use of $[ is deprecated.) So in general you can assume that scalar(@whatever) == $#whatever + 1;

So tell me, is this a Perl 5.6 bug that's known about but not discussed in polite company, are the Perl docs contrary and confusing, or has someone been slipping something into my Pepsi?

Alakaboo

Replies are listed 'Best First'.
RE: Arrays: Last-index special variable vs. scalar values
by btrott (Parson) on Nov 16, 2000 at 00:20 UTC
    You have a slight confusion, it seems, over what "index of the last element" means. You seem to think it means "value of the last element." It doesn't.

    If you have:

    @a = (1,3,5);
    the index of the last element is 2, because
    $a[2]
    is the last element. The *value* of the last element is "5", but that's neither here nor there.

    Does that make sense?

(Guildenstern) RE: Arrays: Last-index special variable vs. scalar values
by Guildenstern (Deacon) on Nov 16, 2000 at 00:23 UTC
    Why should that 2 be a 5? Saying $#ary2 will give you the index of the last array element, in this case 2. I've never seen anywhere that says $# should return the value of the last element. This makes perfect sense with the use of scalar(@ary2) as well. Witness:
    scalar(@ary2) == $#ary2 - $[ +1 scalar(@ary2) == 2 - 0 +1 scalar(@ary2) == 3 3 == 3

    Makes sense to me.

    Guildenstern
    Negaterd character class uber alles!
(doh) RE: Arrays: Last-index special variable vs. scalar values
by mwp (Hermit) on Nov 16, 2000 at 00:30 UTC
    And thus the fine tradition of me proving there is such a thing as a stupid question continues. *looks around for a method of downvoting himself*

    There must have been something in my Pepsi. Really!

    Update: Just to clarify things a little more, I understand the principles behind $#array I just had a major brain fart. I mean, major. So ya'll can stop beating the dead horse, one wouldn't have thought it possible after the beating I gave it.

    Alakaboo
    "Who gave HIM a Perl interpreter?"

Re: Arrays: Last-index special variable vs. scalar values
by snax (Hermit) on Nov 16, 2000 at 13:35 UTC
    You seem to be confusing the concepts of arrays and lists.

    By assigning the list to an array, you force the list to lose its list "magic", so that evaluating it in a scalar context no longer returns the last value but the number of elements.

    Reread perlman:perldata more carefully :) In fact, the answer is in the last quoted section above!

      (I realize this question has been settled... just thought I'd clarify the above answer so there was no need to go to the docs)

      From the Camel Book 2d ed. p47
      In a list context, the value of the list literal is all the values of the list in order. In a scalar context, the value of a list literal is the value of the final element, as with the C comma operator, which always throws away the value on the left and returns the value on the right. For Example:
      @stuff = ("one","two","three");
      assigns the entire list value to array @stuff, but:
      $stuff = ("one","two","three"); assigns only the value three to variable $stuff.

      ----
      Lists are different animals than arrays. Lists are not simply collections of literals. You can have a list of arrays. It seems like if you evaluate a hash in scalar context, i.e $x = (%hash); you get some funky fraction that doesn't mean much. If you did $x = (@ary1,@ary2); you'd get the last value of @ary2. I'm sure that's useful.

        Say tenatious:

        > If you did $x = (@ary1,@ary2); you'd get the last value of @ary2.
        Sorry, but that is not correct.

        The comma operator propagates the scalar context to @ary1 and @ary2. In scalar context, the array expressions turn into the number of elements in each array. So if @ary1 has 10 elements and @ary2 has 20 elements, the expression above is like $x = (10,20), and $x is assigned the number 20.

        Says tenatious:
        >It seems like if you evaluate a hash in scalar context, >i.e $x = (%hash); you get some funky fraction that doesn't mean much.
        It's in the manual what it means. (Check perldata.) Probably the most useful thing about it is that it is false if the hash is empty and true if the hash is not empty, so you can use this:

        if (%hash) { # it is not empty }
        to test for an empty hash.

        But yes, the fraction is information about the internal structure of the hash, and not usually useful. It tells you how many of the hash structure's internal 'buckets' have been used. 11/32 means that there are 32 buckets, and 11 of the buckets have some data in them.

        Low-valued fractions mean that Perl's hashing algorithm is performing badly and the hash will have slower access. What you really want here is for the numerator of the fraction to be exactly equal to the number of keys in the hash. When this happens, every key has its own bucket and looking up keys is fast. When many keys are in the same bucket, Perl has to spend time searching through all the keys in the bucket looking for the one you want.

        I have a program somewhere that exercises the worst-case behavior for Perl's hashes: It constructs a hash that has 10,000 keys, all of which are in the same bucket. Accessing this hash is very slow! The program looks at the funny fraction returned by %h in scalar context to check to make sure it is going the right thing. If the numerator of the fraction ever climbs above 1, the program knows that something has gone wrong!

Re: Arrays: Last-index special variable vs. scalar values
by zodiac (Beadle) on Nov 16, 2000 at 17:52 UTC
    something in your pepsi ... but to confuse you even more look at this:
    $#array = 10;
    yealds in @array having max index of 10 i.e. 11 elements

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://41862]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (6)
As of 2024-04-19 17:57 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found