在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循环变量”错误。
答案 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中找到。