2010-06-04 3 views
3

I строка ниже строки 9 создает локальную копию хэша. Любые изменения в% d не будут содержать изменения глобальной переменной% h (строка: 5). Я должен использовать ссылку (строка: 8), чтобы внести изменения в% h.хеш разыменования без создания локальной копии

Есть ли какой-либо способ разыменования хэша в sub без создания локальной копии? Я спрашиваю, так как у меня сложная запись со многими ссылками и перемещение вокруг нее с помощью разыменований было бы намного проще.

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 в подпункте. Я хотел бы изменить контекст% h в sub с% d. Всякий раз, когда я создаю% 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

Из любопытства - что случилось с двумя указанными вами методами (встроенное разыменование с помощью $$ и оператора стрелки)? –

+0

$$ is okey. Мне просто интересно. – name

ответ

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 

Это является довольно проработанную технику, поэтому обязательно прочитайте документы Perl по local и typeglobs, чтобы вы точно понимали, что происходит (в частности, любые подназры, вызываемые из подпрограммы a после того, как local также будет иметь %alias в области видимости, поскольку local обозначает динамическая область. ион закончится, когда a возвращается.)

Если вы можете установить Data::Alias или один из других алиасов модулей из CPAN вы можете избежать переменный пакета и создать лексический псевдоним. Вышеуказанный метод - единственный способ сделать это без дополнительных модулей.

+0

Согласны, псевдонимы лучше избегать, если у вас есть * действительно хорошая причина * для их использования. Мне любопытно, почему OP отвергает просто использование ссылки. – Ether

+0

thx, вот что я искал. – name

1

ли это поможет вам

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

?

0

Следующий код показывает, как разыменовать с помощью оператора стрелки (и да, без создания локальной переменной)

Read 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. Не следует изменять состояние любых переменных после их назначения.
Смежные вопросы