在Perl中,@ array [1]和$ array [1]之间有什么区别?

时间:2011-10-05 07:00:13

标签: arrays perl

我一直在研究array slices,坦率地说,看不出选择@array[1]$array[1]之间的区别。有区别吗?

#!/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";

5 个答案:

答案 0 :(得分:12)

This is a FAQ.

这两种形式可能在许多情况下以相同的方式工作(但不是全部,正如您可以从常见问题解答中的示例中看到的那样),但$array[1]更清楚地表达了意图。

答案 1 :(得分:11)

$@被称为sigils:听到sigils告诉你的内容

当你看到$时,你正在处理一件事。 当您看到@时,您会看到一系列事项。

@array[ 1 ]是一个切片,包含@array列表中所选元素的列表。你在这个切片中只放了一个元素,@array的第二个元素,但无论如何它都是一个列表。

$array[ 1 ]是列表的第二个元素,单个值,标量。

@hash{ 'one', 'two' }是另一种切片:这次我们切片哈希(%hash),获取一个包含与密钥onetwo对应的值的列表。

区别在哪里?虽然差异很小,但是当您需要单个值时,应避免使用单个元素切片。请记住,在表达式的右侧,单个元素切片的行为类似于标量,但当它们位于表达式的左侧时,它们将成为列表赋值:它们为表达式提供列表上下文。

如果你对标量和列表上下文之间的区别感到不舒服,请不要使用单个元素切片以避免在某些情况下出现意外结果(例如使用行输入操作符{{1}时})。

检查文档和快乐的Perl。

答案 2 :(得分:4)

你已经得到了基思和马可的回答:@表示列表,$表示标量(单值)。我还有更多要补充的内容,不适合评论。

您没有注意到差异,因为您正在使用一个元素的切片。但是,试试这个:

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"

以下是您的代码的一些指示。

use strict;
use warnings;

没有理由不使用这两个。几乎没有任何情况可以更好 - 或更容易 - 不使用它们。当您尝试学习perl时,这尤其适用。

如果您已经使用了警告,那么您将获得以下附加信息:

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

这基本上就是你在这里给出的答案,尽管在perl编译器的简洁语言中说过。

另外,使用print的方式对你来说很难。利用perl的灵活性:

#!/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]


";

如您所见,这将以所见即所得的方式打印出换行符。

答案 3 :(得分:0)

有两点不同:

  1. 对于数组切片(1),在列表上下文中计算«@foo[1]»,但在数组索引($foo[1])的情况下,在标量上下文中计算。这没有功能效果。
  2. @foo[1]发出警告。

答案 4 :(得分:0)

好问题 - 这里有一些不同之处:

$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

切片是否为[1]无关紧要。您可以通过查找在不同上下文中进行评估时给出不同结果的函数来创建更多示例。

后者(第4)例的说明:
$中的$a[0]会创建标量上下文。上下文会影响逗号运算符的工作方式,从而产生不同的结果:

二进制”,“是逗号运算符。在标量上下文中,它会计算其左参数,抛出该值,然后计算其右参数并返回该值。
http://perldoc.perl.org/perlop.html#Comma-Operator

因此:b

要理解以@a[0]开头的行,请考虑:

($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  

看起来行开头的括号会创建一个列表上下文。这几乎就是它所说的:http://docstore.mik.ua/orelly/perl4/prog/ch02_07.htm分配给标量列表也为右侧提供了一个列表上下文,即使列表中只有一个元素

在行的开头

@也会创建一个列表上下文:

@a[0] = ("a", "b")表示以与上述相同的方式评估RHS,即丢弃“b”