3

作为一个新手,我正在尝试使用来自 atlanta perl mongers 的材料来探索 perl 数据结构,可在此处获得Perl Data Structures

这是我编写的示例代码,与其他两个 pragma01.pl相同,02.pl01.pl包含两个 pragma: use strict; use warnings;

#!/usr/bin/perl

my %name = (name=>"Linus", forename=>"Torvalds");
my @system = qw(Linux FreeBSD Solaris NetBSD);

sub passStructure{
  my ($arg1,$arg2)=@_;

  if (ref($arg1) eq "HASH"){
    &printHash($arg1);
  }
  elsif (ref($arg1) eq "ARRAY"){
    &printArray($arg1);
  }

  if (ref($arg2) eq "HASH"){
    &printHash($arg2);
  }
  elsif (ref($arg2) eq "ARRAY"){
    &printArray($arg2);
  }
}

sub printArray{
  my $aref = $_[0];

  print "@{$aref}\n";
  print "@{$aref}->[0]\n";
  print "$$aref[0]\n";          
  print "$aref->[0]\n";
}

sub printHash{
  my $href = $_[0];

  print "%{$href}\n";
  print "%{$href}->{'name'}\n";
  print "$$href{'name'}\n";
  print "$href->{'name'}\n";
}

&passStructure(\@system,\%name);

上述文件中提到的几点我误解了:

第 1 页 44 提到这两种语法结构:"$$href{'name'}"并且"$$aref[0]"永远不应该用于访问值。为什么 ?似乎在我的代码中它们工作正常(见下文),而且 perl 抱怨使用@{$aref}->[0]as deprecated,那么哪一个是正确的?

第 2 页 45 提到没有"use strict"和使用"$href{'SomeKey'}"when"$href->{'SomeKey'}"应该使用,%href是隐式创建的。所以如果我理解得很好,下面的两个脚本都应该打印“Exists”

    [pista@HP-PC temp]$ perl -ale 'my %ref=(SomeKey=>'SomeVal'); print $ref{'SomeKey'}; print "Exists\n" if exists $ref{'SomeKey'};'
    SomeVal
    Exists

    [pista@HP-PC temp]$ perl -ale '                              print $ref{'SomeKey'}; print "Exists\n" if exists $ref{'SomeKey'};'

但第二个不会,为什么?

两个开头提到的脚本的输出:

[pista@HP-PC temp]$ perl 01.pl 
Using an array as a reference is deprecated at 01.pl line 32.
Linux FreeBSD Solaris NetBSD
Linux
Linux
Linux
%{HASH(0x1c33ec0)}
%{HASH(0x1c33ec0)}->{'name'}
Linus
Linus
[pista@HP-PC temp]$ perl 02.pl 
Using an array as a reference is deprecated at 02.pl line 32.
Linux FreeBSD Solaris NetBSD
Linux
Linux
Linux
%{HASH(0x774e60)}
%{HASH(0x774e60)}->{'name'}
Linus
Linus
4

4 回答 4

5

很多人认为$$aref[0]$aref->[0]而不丑。其他人不同意;前一种形式没有任何问题。

@{$aref}->[0]另一方面,这是一个错误,碰巧有效,但已被弃用,可能不会继续存在。

您可能想阅读http://perlmonks.org/?node=References+quick+reference

一个包变量%href是简单地通过提及这样一个没有use strict "vars"效果的散列来创建的,例如通过->省略$href->{'SomeKey'}. 这并不意味着创建了特定的密钥。

更新:查看 Perl Best Practices 参考资料(这本书激发了更多的盲目采用和更少的实际想法,而不是作者预期的),它特别推荐这种->形式以避免留下印记的可能性,从而导致上面提到的问题第 45 页。

于 2013-01-13T23:35:38.447 回答
3

Perl 有普通的数据类型和对数据类型的引用。重要的是,您要了解它们之间的区别,无论是在含义上还是在语法上。

Type   |Normal Access | Reference Access | Debatable Reference Access
=======+==============+==================+===========================
Scalar | $scalar      | $$scalar_ref     |
Array  | $array[0]    | $arrayref->[0]   | $$arrayref[0]
Hash   | $hash{key}   | $hashref->{key}  | $$hashref{key}
Code   | code()       | $coderef->()     | &$coderef()

使用该$$foo[0]语法访问 hashrefs 或 arrayrefs 被认为是不好的原因是(1)双符号看起来像标量 ref 访问令人困惑,并且(2)这种语法隐藏了使用引用的事实。取消引用箭头->的意图很明确。我在这个答案中介绍了为什么使用&印记不好的原因。

@{$aref}->[0]是非常错误的,因为您要取消引用对数组的引用(根据定义,它不能是引用本身),然后用箭头取消引用该数组的第一个元素。有关正确的语法,请参见上表。

将散列插入字符串很少有意义。哈希的字符串化表示已填充和可用存储桶的数量,因此可以告诉您有关负载的信息。这在大多数情况下没有用。此外,不将%字符视为字符串中的特殊字符允许您使用printf……</p>

关于 Perl 数据结构的另一个有趣的事情是知道何时创建了散列或数组中的新条目。通常,访问一个值不会该散列或数组中创建一个槽,除非您使用该值作为引用。

my %foo;
$foo{bar}; # access, nothing happens
say "created at access" if exists $foo{bar};
$foo{bar}[0]; # usage as arrayref
say "created at ref usage" if exists $foo{bar};

输出:created at ref usage

实际上,arrayref 就位,因为undef在某些情况下您可以将值用作引用。然后这个 arrayref 填充散列中的槽。

如果没有use strict 'refs',变量(但不是该变量中的槽)就会出现,因为全局变量只是代表命名空间的哈希中的条目。$foo{bar}与 相同 与$main::foo{bar}相同$main::{foo}{bar}

于 2013-01-13T23:58:19.297 回答
1

$arg->[0]与表单相比,表单的主要优点是$$arg[0]第一种类型更清楚地知道发生了什么……$arg是一个 ARRAYREF,您正在访问它所引用的数组的第 0 个元素。

初读时,第二种形式可以解释为${$arg}[0](取消引用 ARRAYREF)或${$arg[0]}(取消引用 of 的第一个元素@arg

当然,只有一种解释是正确的,但我们都有那些日子(或夜晚)在看代码,我们不太记得顺序运算符和其他句法设备是在什么情况下工作的。此外,如果有的话,混乱会加剧是额外的取消引用级别。

防御性的程序员往往会错误地努力使他们的意图明确,我认为这$arg->[0]是对该代码意图的更明确的表示。

至于哈希的自动创建......它只是将被创建的哈希(以便 Perl 解释器检查密钥是否存在)。未创建密钥本身(自然...您不想创建要检查的密钥...但是如果存储桶不存在,您可能需要创建将保存该密钥的存储桶. 这个过程被称为自动存活,你可以在这里阅读更多关于它的信息。

于 2013-01-13T23:48:21.673 回答
0

我相信您应该以 @{$aref}[0] 或 $aref->[0] 的形式访问数组。

print语句不实例化对象。隐式创建的意思是您不需要在分配变量之前预定义变量。由于print未分配变量,因此不会创建。

于 2013-01-13T23:04:35.377 回答