是否有可能在perl中使用散列哈希(而不是hashrefs)?

时间:2014-04-30 21:02:11

标签: perl hash syntax multidimensional-array nested

在perl中,可以使用哈希,例如my %a = (2, "two");以及hashref,例如my $b = {2 => "two"};

每当我创建一个多维哈希时,顶级哈希的值总是hashrefs,即在它们上面调用ref()会返回"HASH"。是否有可能只有哈希值,没有额外的间接级别?

此外,在使用哈希散列时,perl允许在访问子哈希元素时省略解除引用运算符:

my %a;
$a{2} = {2 => "two"};

# the following are both valid:
$a{2}->{2}
$a{2}{2}

我认为第二个只是第一个语法糖。但是,这似乎与简单的非嵌套hashref所需的语法不一致,因为$b->{2}有效而$b{2}不是。

我的理由是,我希望能够说出

for my %hash (values %a) { 

甚至

for my %hash (map(%{$_}, values %a)) {

但这两个都会在编译时导致“缺少$ on循环变量”错误。

3 个答案:

答案 0 :(得分:7)

一开始,只有标量,散列和数组。实际上,这就是Perl4,但是在设计Perl5时,绝对向后兼容性是一个关键点。这意味着$hash{entry} = @array必须继续将数组大小分配给该哈希条目,而不是将数组放入哈希。所以集合只能包含标量。

这是需要引用的主要原因之一 - 哈希引用和数组引用允许我们将集合称为单个标量事物。哈希引用的语法需要与哈希的语法不同。取消引用箭头->(从C借用)可用于hashref访问:$hashref->{entry}。由于散列永远不能直接包含集合,因此在散列和hashref之间消除歧义时,下标之间的取消引用箭头是不必要的,因此$ref->{a}->{b}$ref->{a}{b}执行相同的操作。但是,hashref访问不能使用$ref{entry},因为该语法已用于散列访问,因为$name%name可以同时存在于单独的变量中。

简而言之,语法很丑陋,但出于向后兼容的原因。

目前,据我所知,for my %hash (@hash_references)for my @array (@hash_references)是不允许的。我个人认为这种语法没有任何问题,但隐式解除引用无疑是相当混乱的。必须使用%$ref而不是%hash并不是那么糟糕。

顺便说一句,Perl6摆脱了引用,因为除了向后兼容性之外,哈希和hashref之间的这种差异是非常不必要的。集合变量的行为更像是标量,尽管有一些新的上下文如“项目上下文”来帮助缺少引用。

答案 1 :(得分:3)

不,哈希值总是标量。散列和数组不是标量,因此不能是散列值,但对它们的引用是标量,因此可以是散列值。

perldata文档页面的第一段说(我的重点):

  

Perl有三种内置数据类型:标量,标量标量,关联数组标量,称为"哈希"。标量是单个字符串(任何大小,仅受可用内存限制),数字或对某事物的引用(将在perlref中讨论)。普通数组是由数字索引的标量的有序列表,从0开始。散列是由其关联的字符串键索引的标量值的无序集合。

答案 2 :(得分:1)

  

是否有可能只有哈希值,没有额外的间接级别?

没有。其他语言隐含地按照你的要求做,但另一方面,他们没有标量和列表上下文,可以在perl中找到。