Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

What is the difference between $array[1] and @array[1]?

by vinoth.ree (Parson)
on Apr 07, 2009 at 14:00 UTC ( #756029=perlquestion: print w/ replies, xml ) Need Help??
vinoth.ree has asked for the wisdom of the Perl Monks concerning the following question:

What is the difference between $array[1] and @array[1]?

Comment on What is the difference between $array[1] and @array[1]?
Download Code
Re: What is the difference between $array[1] and @array[1]?
by moritz (Cardinal) on Apr 07, 2009 at 14:08 UTC
    The context, and that the second one warns when warnings are in effect:
    $ perl -E 'sub w { say wantarray ? "list" : "item" }; @a[0] = w(); $a[ +0] = w()' list item

    (Update: slightly clearer code)

Re: What is the difference between $array[1] and @array[1]?
by morgon (Deacon) on Apr 07, 2009 at 14:21 UTC
    $array[1] is the second array element i.e. a scalar.
    @array[1] is an array-slice (i.e. an array), consisting of the second array element.

    (If you use slices with just one element you will get a warning though.)

    But you can use a whole list in a slice like this:

    my @array = qw(a b c d e); my @slice = @array[0, 2, 4]; print join "-", @slice; # this produces "a-c-e"
    See "perldoc perldata".
      (If you use slices with just one element you will get a warning though.)

      That depends on how you write the slice:

      @a = (1 .. 5); say @a[1]; # Warning say @a[1..1]; # No warning say @a[1,]; # No warning @b = 1; say @a[@b]; # No warning
      Four one element slices, but only one warns.

      Frankly, I find the warning a bit silly; specially the warning if the slice is used in rvalue context. There isn't anything else the programmer could have reasonably meant. And in Perl6, @a[1] is going to be the required syntax anyway.

      Also, @array[1] drives a list context whereas $array[1] would drive scalar context. Hence:

      @array[1] = @another_array;
      will behave differently than
      $array[1] = @another_array;
      The former will put the index (i.e., the number of elements in @another_array minus one) of the last element in @another_array in the first element of @array; whereas the second will put the number of elements in @another_array in the first element of @array.

      Similarly, if you use @array1 as input to a function that behaves differently in list context vs. scalar context, the use of @array[1] will result in list context behavior, whereas $array[1] will result in scalar context behavior (hence, actually, the differences shown above in my example).

      ack Albuquerque, NM
        No, the first one will put the first element of @another_array into @array.

        > perl -e '@a=(5,6,7); @array[1] = @a; print @array;' 5
        Similarly, if you use @array[1] as input to a function that behaves differently in list context vs. scalar context, the use of @array[1] will result in list context behavior, whereas $array[1] will result in scalar context behavior
        What kind of rubbish statement is that? The scalar vs list behaviour of a function is determined by its context, not the sigils of its arguments.

        Suppose you were right, what behaviour would func have below:

        func $foo[1], @bar[1]
        scalar, or list?

        The only difference between $arr[1] and @arr[1] lie in the cases were it can give context: lvalue context. In rvalue context, there isn't one iota of difference (which, IMO, means the warning is utterly bogus if triggered in rvalue context).

        There is a difference between $arr[EXPR] and @arr[EXPR], where EXPR isn't a scalar literal; the former gives scalar context to EXPR, the latter gives list context. But just where it makes a difference, Perl remains silent (rightly so, of course).

        Considering this is a warning about something that can be determined by a static inspection of the code (@{$arr}[1] doesn't trigger for instance), IMO, such a warning belongs in a linter. Perl::Critic for instance.

Re: What is the difference between $array[1] and @array[1]?
by ikegami (Pope) on Apr 07, 2009 at 14:32 UTC
    In practice, very little except for the warning.
    >perl -we"@x = @x[1]" Scalar value @x[1] better written as $x[1] at -e line 1.

    Use $ unless you mean to fetch more than one element from the array at time.

    my $ele = $array[1]; # Array index my @eles = @array[1,2,3]; # Array slice

    Think of it this way: The sigil indicates the kind of value being returned. If you want a scalar, use the scalar sigial ($). If you want an list, use the array sigil (@). While Perl won't care in most situations, it'll signal your intent to the next person to read your code.

      If you want a scalar, use the scalar sigial ($). If you want an list, use the array sigil (@). While Perl won't care in most situations, it'll signal your intent to the next person to read your code.

      Does that mean you disagree with the warning? Or are you like the ancient Greek who didn't consider 1 not to be a proper number, and you don't consider one-element lists to be proper lists?

      I appreciate the idea that a leading $ signals you want a single element, and a leading @ signals you want a slice. But sometimes, the slice one wants is just one element.

        Does that mean you disagree with the warning?

        It's meant to enforce style, but I agree with the style being enforced, and it can detect typos (refactoros?).

        Or are you like the ancient Greek who didn't consider 1 not to be a proper number, and you don't consider one-element lists to be proper lists?

        Do you honestly think in terms of lists when you do $a[4]? I don't.

        But sometimes, the slice one wants is just one element.

        Of course. I didn't mean to imply otherwise. Note that Perl doesn't warn when you don't use a constant.

        $ perl -wle'my @a = qw( a b c ); my @i = 2; print @a[@i]' c

        In fact, using $ wouldn't work in that situation.

        $ perl -wle'my @a = qw( a b c ); my @i = 2; print $a[@i]' b

        I can't figure out what you think I was saying, but hopefully this clears it up.

Re: What is the difference between $array[1] and @array[1]?
by TimToady (Parson) on Apr 07, 2009 at 16:12 UTC
    Another mental tidbit: to prevent just this sort of confusion, Perl 6 makes sigils invariant, so that $array[1] always dereferences $array and @array[1] always deferences @array. (And in either case, slices arise naturally when you use multiple subscripts.)

    So in Perl 6, not only does @array[1] not warn, but it's actually the correct form to dereference @array. The ramifications of this run deep, so I tend to doubt whether this feature will ever be backported to Perl 5, but you never know...

Re: What is the difference between $array[1] and @array[1]?
by sundialsvc4 (Monsignor) on Apr 07, 2009 at 16:32 UTC

    As you have seen (and may know...) the preceding character, "$" or "@", defines the context in which the subsequent phrase will be interpreted.

    Context is a concept that is fairly unique to Perl, AFAIK.

      I can't speak for anything other than PHP and JavaScript (I know, I know... extremely ugly languages), but they both use the same symbol to represent what we know in Perl as scalars, lists, and hashes.

      I also could add that this allows for extremely messy and poor practices in code. I've seen this many times:
      <?php $foo = 'bar'; $foo['bar'] = 'ding'; ?>

      I'm assuming (as I've never looked at the PHP source code) that there are actually two separate variables here, one an array and one a scalar. But then, what happens when you try to do "if ($foo)"?

      Naming two variables the same, @foo and $foo, isn't the best practice in Perl, but at least it's possible ;) .
        It used to be that in Perl, a '$' introduced a scalar value/variable (1 value), a '@' a list value/array (0, 1 or more values) and a '%' a hash variable. Life was simple, and sigils easy to explain.

        Then we got perl5 and objects, and expressions like $obj->method, where the sigil is '$' even if the method is going to return multiple values. Life no longer is simple, and people got the feeling sigils are wrong and Perl6 will change how sigils are used.

Re: What is the difference between $array[1] and @array[1]?
by Anonymous Monk on Apr 20, 2009 at 13:17 UTC
    This exact question comes from perlfaq4

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://756029]
Approved by lakshmananindia
Front-paged by targetsmart
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (6)
As of 2014-07-23 04:08 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (133 votes), past polls