Re: What is the difference between $array[1] and @array[1]?
by morgon (Priest) 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". | [reply] [d/l] [select] |
|
@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. | [reply] [d/l] [select] |
|
@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).
| [reply] [d/l] [select] |
|
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. | [reply] [d/l] [select] |
|
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
| [reply] [d/l] |
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... | [reply] [d/l] [select] |
Re: What is the difference between $array[1] and @array[1]?
by ikegami (Patriarch) 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.
| [reply] [d/l] [select] |
|
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.
| [reply] |
|
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.
| [reply] [d/l] [select] |
|
|
|
|
|
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) | [reply] [d/l] |
Re: What is the difference between $array[1] and @array[1]?
by sundialsvc4 (Abbot) 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 ;) . | [reply] [d/l] |
|
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.
| [reply] [d/l] |
Re: What is the difference between $array[1] and @array[1]?
by Anonymous Monk on Apr 20, 2009 at 13:17 UTC
|
| [reply] |