微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Perl 散列的散列原理

如何解决Perl 散列的散列原理

我决定尝试一下 Perl,我偶然发现了一种似乎有效的语言结构,但我简直不敢相信。我想这背后有一些道理,所以我决定问一个问题。

采用以下 Perl 代码

%data = ('John Paul' => ('Age' => 45),'Lisa' => 30);
print "\$data{'John Paul'} = $data{'John Paul'}{'Age'}\n";
print "\$data{'Lisa'} = $data{'Lisa'}\n";

我的目的是检查散列的散列是如何工作的。上面的代码打印:

$data{'John Paul'} =
$data{'Lisa'} =

要使其成为需要的有效散列值:

%data = ('John Paul' => {'Age' => 45},'Lisa' => 30);

结果是:

$data{'John Paul'} = 45
$data{'Lisa'} = 30

有谁知道:

  1. 为什么存在不一致且内部散列需要 {} 而不是 ()
  2. 当内部哈希值是 () 而不是 {} 时,为什么我没有收到错误或警告出现问题?很容易犯这样的错误。此外,('Age' => 45) 不仅会破坏 'John Paul' 的值,还会破坏 'Lisa' 的值。我无法想象在数千行代码的项目中搜索这种“错误”。

解决方法

( 'John Paul' => ( 'Age' => 45 ),'Lisa' => 30 )

只是另一种写作方式

'John Paul','Age',45,'Lisa',30

Parens 不创建任何数据结构;它们只是像 (3+4)*5 一样影响优先级。我们不写的原因

my %h = a => 4;

或等价物

my %h = 'a',4;

是它会被解释为

( my %h = 'a' ),4;

创建哈希的是 my %data,而不是括号。赋值的右侧只是在堆栈上放置了任意数量的标量,而不是散列。赋值运算符将这些标量添加到哈希中。


但有时,我们想创建一个匿名哈希。这就是 {} 的用武之地。

my %data = ( 'John Paul' => { 'Age' => 45 },'Lisa' => 30 );

基本上等价于

my %anon = ( 'Age' => 45 );
my %data = ( 'John Paul' => \%anon,'Lisa' => 30 );

请注意,\%anon 返回标量,即对哈希的引用。这与 ( 'John Paul' => \%anon,'Lisa' => 30 )'John Paul' => \%anon,'Lisa' => 30 返回的四个标量有着根本的不同。


为什么不统一,内部散列需要 {} 而不是 ()

这个问题的一个基本前提是错误的:哈希不需要 ()。例如,以下是完全有效的:

my %h1 = 'm'..'p';
sub f { return x => 4,y => 5 }
my %h2 = f();
my %h3 = do { i => 6,j => 7 };

() 与哈希无关。缺乏统一性源于缺乏平行性。一种使用 {} 创建哈希。一种使用 () 来覆盖优先级。

由于括号只影响优先级,所以可以使用

my %data = ( 'John Paul' => ({ 'Age' => 45 }),'Lisa' => 30 );  # ok (but weird)

这与以下非常不同:

my %data = ( 'John Paul' => ( 'Age' => 45 ),'Lisa' => 30 );  # XXX

当内部散列使用 () 而不是 {} 时,为什么我没有收到错误或警告有问题?

不仅使用 () 有效,通常还需要在包含逗号的表达式周围使用 ()。那么它到底应该在什么时候发出警告呢?关键是这应该是警告还是 perlcritic 发现的东西,至少乍一看是有争议的。后者肯定会找到这个,但我不知道它是否存在规则。

,

为什么不统一,内部散列需要 {} 而不是 ()?

对散列的赋值是一个标量列表(在键和值之间交替)。

你不能有一个散列(因为它不是标量)作为那里的值,但你可以有一个散列引用。

列表变得扁平。

当内部散列使用 () 而不是 {} 时,为什么我没有收到错误或警告有问题?

因为您没有使用 the use strict; use warnings; pragmas 开启它们(默认情况下由于向后兼容性太差而关闭,但将是 on by default in Perl 7)。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。