3

次のコードの 9 行目は、ハッシュのローカル コピーを作成します。%d を変更しても、グローバル %h 変数 (行: 5) は変更されません。%h に変更を加えるには、参照 (行: 8) を使用する必要があります。

ローカルコピーを作成せずにサブでハッシュを逆参照する方法はありますか? 多くの参照を含む複雑なレコードがあり、逆参照を使用してナビゲートする方がはるかに簡単であるため、質問しています。

  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
.. }

ローカル コピーを作成せずに %h を指すには、XXXXXXXXX の下に何を入力すればよいですか?

4

4 に答える 4

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 のドキュメントを読み、localtypeglobsが起こっているのかを正確に理解してください (特に、動的スコープを示すため、aの後にサブルーチン内から呼び出されるすべてのサブルーチンlocal%aliasスコープ内にあります。localローカライズは戻った時点で終了しaます。)

Data::Aliasまたは他のエイリアスモジュールのいずれかをインストールできる場合はCPAN、パッケージ変数を回避して字句エイリアスを作成できます。上記の方法は、追加のモジュールなしでそれを行う唯一の方法です。

于 2010-06-04T14:54:02.767 に答える
2

ハッシュ参照を使用する 2 つの方法:

  1. あなた自身が使っていたもの

    $$href{'key2'} = "key2";
    
  2. 上で指摘した:

    $href->{'key1'} = "key1";
    

http://perldoc.perl.org/perlreftut.html

于 2010-06-04T08:46:25.013 に答える
1

これは役に立ちますか

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

?

于 2010-06-04T08:29:27.420 に答える
0

次のコードは、矢印演算子を使用して逆参照する方法を示しています (ローカル変数を作成せずに)

逆参照に関するチュートリアルと、可能なさまざまなタイプの逆参照については、こちらをお読みください。

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. 変数が割り当てられた後は、変数状態を変更しないでください。
于 2010-06-04T10:47:42.167 に答える