访问列表作为哈希表

6

我可以直接访问列表中的元素:

$foo = (qw(a b c))[2]; # $foo = "c"

我可以给哈希分配一个列表:

%h = (a=>0, b=>1, c=>2);
$foo = $h{c}; # $foo = 2

那么,为什么我不能直接将列表视为哈希表呢?
$foo = (a=>0, b=>1, c=>2){c}; # Syntax error

我找到的最接近的方法是创建一个哈希引用:
$foo = {a=>0, b=>1, c=>2}->{c};

如何使用正确的语法将列表作为哈希进行访问?为什么不能这样做?


简短回答:创建哈希是一个相当昂贵的操作,而列表和数组的表示方式非常类似。哈希和列表之间的概念差异也非常大。 - amon
1
只有在将列表分配给哈希变量时才会发生转换,因为这是常见的需求。 - Barmar
2个回答

6

你不能使用列表作为哈希,因为列表不是哈希。 :)

=>("fat comma")运算符与,相同,但有额外的功能,在左侧引用裸字。所以当你写下这个:

( a=>0, b=>1, c=>2 )

这与以下内容完全相同:

( 'a', 0, 'b', 1, 'c', 2 )

这不是哈希,只是一个列表。

列表是暂时存在于堆栈中的东西;正如你正确指出的那样,它们可以分配给数组和哈希,但它们不同于数组和哈希。

在使用哈希之前,需要先构建哈希。分配给哈希的任何键/值列表都需要进行哈希处理,并分配桶并将值放入桶中。因此,当你写:

$foo = {a=>0, b=>1, c=>2}->{c};

正在发生的事情是:
  1. 将列表中的元素('a',0,'b',1,'c',2)放入堆栈中
  2. 通过 { LIST } 运算符构造匿名哈希表
  3. 弹出堆栈中的列表元素,并将它们分配给哈希表,将它们转换为键和值
  4. 返回对该哈希表的引用。
  5. 使用 -> 运算符取消引用
  6. 查找键 c ,并
  7. 返回其值,将表达式简化为 $foo = 2

那么,如果列表不是数组,为什么可以写成 (qw(a b c))[2] 呢?嗯,内部堆栈只是一组SV * 的数组,所以我想使其能够支持下标操作很简单,而且看起来是个好主意。

这里有一篇由一个非常酷的家伙撰写的文章,你也可能会觉得很有启发:Perl 中的数组与列表:有什么区别?


0
不行。因为列表不是哈希表。 你能做到的最接近的是:
my $foo = (a=>0,b=>1,c=>2)[5]; 
printf("$foo\n");

这将会打印

2

由于上述代码完全相同

my $foo = ('a',0,'b',1,'c',2)[5]; 
printf("$foo\n");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接