为什么你需要在访问阵列和哈希元素在Perl?
题
因为阵列和哈希只能含有标量在Perl,为什么你必须使用美元来告诉译员,值标在访问阵列或哈希元素呢?换句话说,假定你有一个数组 @myarray
哈希 %myhash
, 为什么你需要做的:
$x = $myarray[1];
$y = $myhash{'foo'};
而不是仅仅这样做:
$x = myarray[1];
$y = myhash{'foo'};
为什么是上述含糊不清?
它不会被非法Perl代码,如果它是什么,但美元的在那个地方?例如,不是所有的下列非法的,在Perl?
@var[0];
@var{'key'};
%var[0];
%var{'key'};
解决方案
切片不是非法的:
@slice = @myarray[1, 2, 5];
@slice = @myhash{qw/foo bar baz/};
我怀疑这是你需要指定是否要从哈希/数组中获取单个值的部分原因。
其他提示
我刚刚用过
my $x = myarray[1];
在一个程序中,令我惊讶的是,这是我运行时发生的事情:
$ perl foo.pl
Flying Butt Monkeys!
那是因为整个程序看起来像这样:
$ cat foo.pl
#!/usr/bin/env perl
use strict;
use warnings;
sub myarray {
print "Flying Butt Monkeys!\n";
}
my $x = myarray[1];
因此,myarray调用一个子例程,向它传递一个包含单个元素的匿名数组的引用,1。
这是你需要在数组访问上使用sigil的另一个原因。
sigil为您提供容器的返回类型。因此,如果某些事情以@
开头,您就知道它会返回一个列表。如果以$
开头,则返回标量。
现在如果sigil之后只有一个标识符(比如$foo
或@foo
,那么它就是一个简单的变量访问。如果它跟着一个[
,那么它就是一个数组访问,如果跟着它的话通过{
,它是对哈希的访问。
# variables
$foo
@foo
# accesses
$stuff{blubb} # accesses %stuff, returns a scalar
@stuff{@list} # accesses %stuff, returns an array
$stuff[blubb] # accesses @stuff, returns a scalar
# (and calls the blubb() function)
@stuff[blubb] # accesses @stuff, returns an array
有些人类语言的概念非常相似。
然而,许多程序员发现令人困惑,因此Perl 6使用了一个不变的sigil。
一般来说,Perl 5编译器想要在编译时知道某些内容是在列表中还是在标量上下文中,因此如果没有前导符号,某些术语就会变得模棱两可。
这是有效的Perl:@var[0]
。它是长度为1的数组切片。 @var[0,1]
将是一个长度为2的数组切片。
@var['key']
无效Perl,因为数组只能用数字索引,而且
另外两个(%var[0] and %var['key']
)是无效的Perl,因为散列片使用{}来索引散列。
@var{'key'}
和@var{0}
都是有效的哈希切片。显然,采用长度为1的切片是不正常的,但它肯定是有效的。
有关在Perl中进行切片的详细信息,请参阅 perldata perldoc的切片部分。
人们已经指出你可以有切片和上下文,但是可以将变量和其他东西分开。您不必知道所有关键字或子例程名称来选择合理的变量名称。这是我在其他语言中想念Perl的重大事项之一。
我可以想到一种方式
$x = myarray[1];
是不明确的 - 如果你想要一个名为m的数组怎么办?
$x = m[1];
除了正则表达式匹配之外,你怎么能说出来呢?
换句话说,语法是帮助Perl解释器,好吧,解释!
在Perl5(将改变在Perl6)符号的指示 上下文 你的表达。
- 你想要一个特定的标出来的散列,所以它的
$hash{key}
. - 你想要的价值的一个特定的老虎的阵列,所以它的
$array[0]
.
然而,正如指出的zigdon, 切片 是合法的。他们解释那些表达形式在一个 列表 上下文。
- 你想要一个列表1的数值在哈希
@hash{key}
工作 但是还有更大的清单的工作,以及像
@hash{qw<key1 key2 ... key_n>}
.你想要几个插槽出的一系列
@array[0,3,5..7,$n..$n+5]
工作@array[0]
是一个名单的尺寸1.
有没有"散列方面",因此既没有 %hash{@keys}
也不 %hash{key}
具有意义。
所以你必须 "@"
+ "array[0]"
<=> < 印记=背景下>+ < 索引表达>作为完整的表达。
印记提供了背景下的访问:
$
指标下的(a scalar 变量或单个元件的散列或一系列)@
装置名单上下文中(a系列,或一片 散列或一系列)%
是一个整个的哈
在Perl 5中你需要sigils($和@),因为裸字标识符的默认解释是子程序调用的默认解释(因此在大多数情况下无需使用<!> amp;)。