为什么我可以使用@list 来调用数组,但不能使用%dict 来调用perl 中的散列?

Why I can use @list to call an array, but can't use %dict to call a hash in perl?

今天开始我的perl之旅,现在我正在探索数据类型。

我的代码如下:

@list=(1,2,3,4,5);
%dict=(1,2,3,4,5);

print "$list[0]\n";         # using [ ] to wrap index
print "$dict{1}\n";         # using { } to wrap key

print "@list[2]\n";
print "%dict{2}\n";

好像$ + var_name对array和hash都有效,但是@ + var_name可以用来调用array,同时% + var_name不能用来调用hash。

为什么?

数组在双引号内插入,因此您会看到打印的数组的实际内容。

另一方面,%dict{1} 有效,但未插入双引号内。因此,my %partial_dict = %dict{1,3} 之类的东西是有效的,并且符合您的预期,即 %partial_dict 现在将具有值 (1,2,3,4)。但是 "%dict{1,3}"(在引号中)仍将打印为 %dict{1,3}.

Perl Cookbook 有一些关于打印哈希值的技巧。

@list[2] 有效,因为它是列表的 切片

在 Perl 5 中,印记表示——在非技术意义上——你的表达式的 上下文。除了切片在标量上下文中的一些非标准行为外,基本思想是印记代表您想要 得到 表达式的内容。

如果您想要散列中的标量,它是 $hash{key}。 如果你想要一个数组中的标量,它是 $array[0]但是,Perl 允许您获得聚合的。这允许您在一个紧凑的表达式中检索多个值。切片采用 list 索引。所以,

@list = @hash{ qw<key1 key2> };

为您提供散列中的项目列表。而且,

@list2 = @list[0..3];

为您提供数组中的前四项。 --> 对于您的情况,@list[2] 仍然有一个 "list" 索引,只是该列表是 "list of one" 的特例。

由于标量和列表上下文定义得相当好,并且没有 "hash context",它在标量 $ 和 "lists" 保持在 @ 并且直到最近,Perl 才支持使用 % 寻址任何变量。所以 %hash{@keys}%hash{key} 都没有意义。但是,现在,您可以通过将 % 印记放在前面来转储具有值的索引对。

my %hash = qw<a 1 b 2>;
my @list = %hash{ qw<a b> }; # yields ( 'a', 1, 'b', 2 )
my @l2   = %list[0..2];      # yields ( 0, 'a', 1, '1', 2, 'b' )

所以,我想,如果您有旧版本的 Perl,则不能,但如果您有 5.20,则可以。


但出于完美主义者的考虑,切片在标量环境中的工作方式并不直观。因为将列表放入标量上下文的标准行为是 count 列表,如果切片适用于该行为:

( $item = @hash{ @keys } ) == scalar @keys;

这将使表达式:

$item = @hash{ @keys };

不比:

更有价值
scalar @keys;

因此,Perl 似乎将其视为表达式:

$s = ( $hash{$keys[0]}, $hash{$keys[1]}, ... , $hash{$keys[$#keys]} );

并且当在标量上下文中评估以逗号分隔的列表时,它会分配最后一个表达式。所以它真的结束了

$item = @hash{ @keys }; 

不比:

更有价值
$item = $hash{ $keys[-1] };

但它使得写这样的东西:

$item = $hash{ source1(), source2(), @array3, $banana, ( map { "$_" } source4()};

比写作稍微容易一点:

$item = $hash{ [source1(), source2(), @array3, $banana, ( map { "$_" } source4()]->[-1] }

但只是轻微的。