为什么在访问Perl中的数组和哈希元素时需要$?

时间:2008-09-30 15:44:45

标签: perl arrays hash sigils

由于数组和散列只能包含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'};

9 个答案:

答案 0 :(得分: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的另一个原因。

答案 1 :(得分:17)

切片不是非法的:

@slice = @myarray[1, 2, 5];
@slice = @myhash{qw/foo bar baz/};

我怀疑这是你需要指定是否要从哈希/数组中获取单个值的部分原因。

答案 2 :(得分:11)

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编译器想要在编译时知道某些内容是在列表中还是在标量上下文中,因此如果没有前导符号,某些术语就会变得模棱两可。

答案 3 :(得分:9)

这是有效的Perl:@var[0]。它是长度为1的数组切片。 @var[0,1]将是长度为2的数组切片。

@var['key']无效Perl,因为数组只能用数字索引,而且 另外两个(%var[0] and %var['key'])是无效的Perl,因为散列片使用{}来索引散列。

不过,

@var{'key'}@var{0}都是有效的哈希切片。显然,采用长度为1的切片是不正常的,但它肯定是有效的。

有关在Perl中进行切片的详细信息,请参阅the slice section of perldata perldoc

答案 4 :(得分:9)

人们已经指出你可以有切片和上下文,但是可以将变量和其他东西分开。您不必知道所有关键字或子例程名称来选择合理的变量名称。这是我在其他语言中想念Perl的重大事项之一。

答案 5 :(得分:7)

我可以想到一种方式

$x = myarray[1];

是不明确的 - 如果你想要一个名为m的数组怎么办?

$x = m[1];

除了正则表达式匹配之外,你怎么能说出来呢?

换句话说,语法是帮助Perl解释器,好吧,解释!

答案 6 :(得分:6)

在Perl 5中(要在Perl 6中进行更改),sigil表示表达式的 context

  • 你想要一个哈希的特定标量,所以它是$hash{key}
  • 您希望特定插槽的值超出数组,因此它是$array[0]

然而,正如zigdon所指出的,切片是合法的。他们在 list 上下文中解释这些表达式。

  • 您希望散列@hash{key}中的1个值列表
  • 但是更大的列表也可以使用,例如@hash{qw<key1 key2 ... key_n>}

  • 你想要一个数组@array[0,3,5..7,$n..$n+5]中的几个插槽

  • @array[0]是一个大小为1的列表。

没有“哈希上下文”,因此%hash{@keys}%hash{key}都没有意义。

所以你有"@" + "array[0]"&lt; =&gt; &LT; sigil = context&gt; +&lt;索引表达式&gt;作为完整的表达。

答案 7 :(得分:4)

sigil提供访问的上下文:

  • $表示标量上下文(标量 变量或散列或数组的单个元素)
  • @表示列表上下文(整个数组或一个切片) 哈希或数组)
  • %是一个完整的哈希

答案 8 :(得分:4)

在Perl 5中你需要sigils($和@),因为裸字标识符的默认解释是子程序调用的默认解释(因此在大多数情况下不需要使用&amp;)。