由于数组和散列只能包含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'};
hexten.. 22
我刚刚用过
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的另一个原因.
我刚刚用过
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的另一个原因.
切片不是非法的:
@slice = @myarray[1, 2, 5]; @slice = @myhash{qw/foo bar baz/};
我怀疑这是你需要指定是否要从哈希/数组中获取单个值的部分原因.
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解释器,好吧,解释!
在Perl 5中(要在Perl 6中进行更改),sigil表示表达式的上下文.
你想要一个哈希的特定标量,所以它是$hash{key}
.
你想要一个特定插槽的值超出一个数组,所以它是$array[0]
.
然而,正如zigdon指出的那样,切片是合法的.他们在列表上下文中解释这些表达式.
您需要哈希@hash{key}
工作中的1个值的列表
但是更大的列表也可以使用@hash{qw
.
你想要一个阵列中的几个插槽@array[0,3,5..7,$n..$n+5]
工作
@array[0]
是一个大小为1的列表.
没有"哈希上下文",所以既没有%hash{@keys}
也没有%hash{key}
意义.
所以你有"@"
+ "array[0]"
<=>