简体   繁体   中英

In Perl, what is the difference between @array[1] and $array[1]?

I have been studying array slices and frankly do not see the difference between choosing @array[1] and $array[1] . Is there a difference?

#!/usr/bin/perl 
@array = (1,3);
print "\nPrinting out full array..\@array\n";
print "@array\n";
print "\n";
print "Printing out \@array[1]\n";
print "@array[1]\n";
print "Printing out \$array[1]\n";
print "$array[1]\n";
print "\n\n";

This is a FAQ.

The two forms are likely to work the same way in many contexts (but not all, as you can see from the example in the FAQ), but $array[1] expresses the intent more clearly.

$ and @ are called sigils: hear what the sigils tell you

When you see $ you are dealing with a single thing. When you see @ you have a list of things.

@array[ 1 ] is a slice, a list with selected elements from the @array list. You have put only an element in this slice, the second element of @array , but it's a list anyway.

$array[ 1 ] is the second element of the list, a single value, a scalar.

@hash{ 'one', 'two' } is another kind of slice: this time we sliced an hash ( %hash ), obtaining a list with values corresponding to keys one and two .

Where's the difference? Although the difference is thin, you should avoid single element slices when you want a single value. Remember that on the right hand side of an expression, single element slices behave like scalars, but when they are on the left hand side of an expression they become a list assignment: they give list context to the expression.

If still you aren't feeling comfortable with the difference between scalar and list context, please don't use single element slices in order to avoid unexpected results in certain situations ( for instance when using the line input operator < > ).

Check the docs and happy Perl.

You already have your answer from Keith and Marco: @ means list, $ means scalar (single value). I have more to add that does not fit in a comment.

You do not notice the difference because you are using a slice of one element. However, try this:

use warnings;
use strict;
use v5.10; # to enable say

my @array = (1 .. 10);
say "@array[2 .. 4]"; # [2,3,4] == "3 4 5"
say "@array[1,4,7]";  #         == "2 5 8"

Here's some pointers to your code.

use strict;
use warnings;

There really is no excuse for not using these two. There is hardly any circumstance where it is better -- or easier -- to not use them. This holds especially true when you are experimenting and trying to learn perl.

If you had been using warnings, you would have gotten this additional information:

Scalar value @array[1] better written as $array[1]

Which basically is exactly the answer you have been given here, albeit said in the perl compiler's terse language.

Also, using print the way you do it is hard on the eyes. Make use of perl's flexibility:

#!/usr/bin/perl 
use strict;
use warnings;

my @array = (1 .. 10);
print "
Printing out full array..\@array
@array

Printing out \@array[1]
@array[1]
Printing out \$array[1]
$array[1]


";

As you can see, this will print out newlines in a WYSIWYG fashion.

There are two differences:

  1. The « 1 » is evaluated in list context in the case of the array slice ( @foo[1] ), but in scalar context in the case of the array indexing ( $foo[1] ). This has no functional effect.
  2. @foo[1] gives a warning.

Good question - here's some differences:

$a[0] = localtime; print @a;  # this prints: Tue Nov 1 18:51:13 2011  
@a[0] = localtime; print @a;  # this prints the amount of seconds, e.g. 13

$a[0] = grep{}, qw(6 2 8); print @a; # this prints: 3  
@a[0] = grep{}, qw(6 2 8); print @a; # this prints: 6

$a[0] = reverse ("a", "b"); print @a; # this prints: ba  
@a[0] = reverse ("a", "b"); print @a; # this prints: b

$a[0] = ("a", "b"); print @a;    # this prints: b  
@a[0] = ("a", "b"); print @a;    # this prints: a

It doesn't matter if the slice is [1] . You can create more examples by finding functions that give different results when evaluated in different contexts.

Explanation of the latter (4th) example:
The $ in $a[0] creates a scalar context. The context affects the way the comma operator works, creating different results:

" Binary "," is the comma operator. In scalar context it evaluates its left argument, throws that value away, then evaluates its right argument and returns that value. "
http://perldoc.perl.org/perlop.html#Comma-Operator

Hence: b

To understand the line beginning with: @a[0] consider:

($a, $b, $c) = ("a", "b", "c", "d"); # here the "d" is discarded
print $a, $b, $c; # this prints: abc

($a, $b)     = ("a", "b", "c");      # here the "c" is discarded  
($a)         = ("a", "b");           # here the "b" is discarded  
($a[0])      = ("a", "b");           # here the "b" is discarded  

It would appear that parentheses at the beginning of the line create a list context. This is pretty much what it says at: http://docstore.mik.ua/orelly/perl4/prog/ch02_07.htm " Assignment to a list of scalars also provides a list context to the righthand side, even if there's only one element in the list "

@ at the beginnning of a line also creates a list context:

@a[0] = ("a", "b") means evaluate the RHS in the same way as above ie discard the "b"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM