2010-06-04 76 views
3

我下面的代码创建散列的本地副本。对%d的任何更改都不会提供对全局%h变量(行:5)的更改。我必须使用参考(行:8)来提供对%h的更改。取消引用散列而不创建本地副本

有没有什么办法可以在不创建本地副本的情况下对子文件中的散列进行反引用? 我在问,因为我有复杂的记录与许多参考和导航周围与解除引用会更容易。

1 #!/usr/bin/perl -w 
    2 use strict; 
    3 use warnings; 
    4 
    5 my %h; 
    6 sub a { 
    7 
    8  my $href = shift; 
    9  my(%d) = %{$href}; # this will make a copy of global %h 
10  
11  $$href{1}=2;  # this will make a change in global %h 
12  $d{2}=2;   # this will not a change in global %h 
13 } 
14 a(\%h); 
15 print scalar (keys %h) . "\n"; 

----------------

感谢您的答复。

问题是我可以在子节点中为%h创建某种“别名/绑定”。 我想改变%d中子%h的上下文。 每当我创建%d时,他都会创建%h的本地副本 - 有什么方法可以避免这种情况,还是必须始终使用引用?

----------------

再一次:)我知道$ href的工作。我阅读教程/手册/文档等 我没有找到答案 - 我认为这是不可能的,因为它不是写在那里,但谁知道。

我要完成这样的行为:

6 sub a { 
    7  $h{"1"}=2; 
    8 } 

这等同于:

6 sub a { 
    8  my $href = shift; 
    11  $$href{1}=2;  # this will make a change in global %h 
    11  $href->{1}=2; # this will make a change in global %h 

现在怎么做,与%d的帮助 - 它实际上是可能的吗?

6 sub a { 
7  my %d = XXXXXXXXX 
.. } 

我应该把XXXXXXXXX下指向%H,而无需创建一个本地副本?

+1

出于好奇 - 你列出的两种方法($$和箭头运算符的内联解除引用)有什么问题? – 2010-06-04 12:05:48

+0

$$是okey。我只是好奇。 – name 2010-06-05 10:48:33

回答

6

要创造价值的本地别名,你需要使用Perl的包变量,可以使用类型团语法别名(和local到范围别名):

#!/usr/bin/perl -w 
use strict; 
use warnings; 

my %h; 

sub a { 
    my $href = shift; 

    our %alias; # create the package variable (for strict) 

    local *alias = $href; 
     # here we tell perl to install the hashref into the typeglob 'alias' 
     # perl will automatically put the hashref into the HASH slot of 
     # the glob which makes %alias refer to the passed in hash. 
     # local is used to limit the change to the current dynamic scope. 
     # effectively it is doing: *{alias}{HASH} = $href 

    $$href{1}=2;  # this will make a change in global %h 
    $alias{2}=2;  # this will also make a change in global %h 
} 
a(\%h); 
print scalar (keys %h) . "\n"; # prints 2 

这是一个相当先进的技术,因此请务必阅读localtypeglobs上的Perl文档,以便您准确理解正在发生的情况(特别是,在a子例程之后调用的任何子程序在范围内也将具有%alias,因为local表示一个动态范围。本地化离子将结束时a回报。)

如果可以安装Data::Alias或从CPAN其它混叠模块可以避开包变量中的一个,并创建一个词汇别名。上述方法是无需额外模块的唯一方法。

+0

同意,别名是最好的避免,除非有一个*真正的好理由*使用它们。我很好奇OP为什么拒绝简单地使用引用。 – Ether 2010-06-04 16:18:27

+0

thx,那就是我一直在寻找的东西。 – name 2010-06-05 10:48:08

1

这是否帮助你

$href->{1} = 2; 
print scalars (keys %{$href}); 

0

下面的代码演示了如何使用箭头操作符取消引用(是的,无需创建一个局部变量)对非关联化的教程和不同类型的非关联化可能的

this

use warnings; 
use Data::Dumper::Simple; 

my %h; 
sub a { 
    my $href = shift; 

    #dereference using the arrow operator - *preferred* 
    $href->{name} = "John"; 

} 

a(\%h); #Passing the reference of the hash 
print Dumper(%h); 

为什么你需要传递一个全局散列,作为第一个子例程的参数?

  1. 避免使用全局变量。
  2. 优选地,在分配变量后,不要更改任何变量的状态。