7

Perl では、文字列に基づいてグローバル変数を作成することは可能ですか?

たとえば、次のような関数があるとします。

sub create_glob_var {
    my ($glob_var_str) = @_;
    # something like this ( but not a hash access).
    our ${$glob_var_str};
};

そして私はそれを次のように呼びました:

create_glob_var( "bar" );

create_glob_varというグローバル変数を実際に作成するように変更するにはどうすればよい$barですか?

私のプロジェクトは perl 5.8.5 を使用しています。

編集

以下は機能しません。

use strict;
BEGIN {
  sub create_glob_var {
    my ($glob_var_str) = @_;
    no strict 'refs';
    $$glob_var_str = undef;  # or whatever you want to set it to
  }

  create_glob_var("bah");
};

$bah = "blah";

プロデュース:

変数「$bah」が /nfs/pdx/home/rbroger1/tmp2.pl 行 12 でインポートされません。
グローバル シンボル「$bah」には、/nfs/pdx/home/rbroger1/tmp2.pl 行 12 で明示的なパッケージ名が必要です。
コンパイル エラーのため、/nfs/pdx/home/rbroger1/tmp2.pl の実行が中止されました。

注:グローバル変数を使用すると、オゾンが枯渇し、男性型脱毛症が発生することを認識しています。グローバル変数の使用ですでに完全に感染しているいくつかのレガシー コードをクリーンアップしようとしています。一度に 1 つのリファクタリング...

4

6 に答える 6

5

古いコードをクリーンアップしようとしている場合は、必要な変数をエクスポートするモジュールを作成できます。を呼び出す必要があると感じるたびにcreate_glob_var、代わりにこのパッケージに変数を追加し、それをインポート リストに入れます。

これは、何が起こっているのか、変数がどのように使用されているのかを追跡するのに役立ちます。

package MyVars;

use strict; use warnings;

use Exporter 'import';

our($x, %y, @z);

our @EXPORT_OK = qw( $x %y @z );

スクリプト:

#!/usr/bin/perl

use strict;use warnings;

use MyVars qw( $x %y @z );

$x = 'test';
%y = (a => 1, b => 2);
@z = qw( a b c);

use Data::Dumper;
print Dumper \($x, %y, @z);

出力:

$VAR1 = \'テスト';
$VAR2 = {
          'a' => 1,
          'b' => 2
        };
$VAR3 = [
          'a',
          'b',
          'c'
        ];
于 2010-02-16T19:44:51.797 に答える
3
sub create_glob_var {
    my ($glob_var_str) = @_;
    no strict 'refs';
    $$glob_var_str = undef;  # or whatever you want to set it to
}

が有効な場合にno strict 'refs'のみ必要use strictであり、常にそうあるべきです。

補遺:

create_glob_var次のコードが成功するようにサブルーチンを記述する方法があるかどうかを尋ねている場合:

use strict;
create_glob_var("bar");
$bar = "whatever";

...では、答えは「いいえ」です。しかし、Perl のvarsプラグマはあなたが望むことを行います:

use strict;
use vars qw($bar);
$bar = "whatever";

しかし、これは一種の古いスタイルの Perl コーディングです。今日では、通常は次のようにします。

use strict;
our $bar = "blah";

our後で自由に使用できるグローバル変数を宣言することもできます。

our ($foo, @bar, %baz);
# ...
$foo = 5;
@bar = (1, 2, 3);
%baz = (this => 'that');
于 2010-02-16T18:58:21.433 に答える
2

を使用する必要がありますがeval、それは一般的に悪と見なされます。何かのようなもの:

eval("$glob_var_str = \@_;");

編集

myと を使用せずにのみこれを実行できることを確認しましno strict refsた。

于 2010-02-16T18:55:33.850 に答える
2

次の質問を見てみてください: Perl には PHP のような動的変数がありますか?

簡単に言えば、できるはずです$$glob_var_str = "whatever";

于 2010-02-16T18:57:50.073 に答える
2

プラグマはすでにあなたが望むもののvarsために重労働をしているので、それを働かせてください:

#! /usr/bin/perl

use warnings;
use strict;
use vars;

BEGIN { vars->import(qw/ $bah /) }

$bah = "blah";
print $bah, "\n";

あなたがそれを綴るのを好むならcreate_glob_var、それから使用してください

#! /usr/bin/perl

use warnings;
use strict;
use vars;

sub create_glob_var { vars->import("\$$_[0]") }

BEGIN { create_glob_var "bah" }

$bah = "blah";
print $bah, "\n";

いずれにせよ、出力は

何とか

これらの変数を で宣言するのではなく、なぜこのようにしたいのか知りたいですour。はい、それらすべてをキャッチするには数回の反復が必要になる場合がありますが、これらはとにかく短期的な修正ですよね?

一般に、変数を変数名として使用できます ( perlref「シンボリック参照」を参照) 。strict 'refs'

Rafael Garcia-Suarez は、「あなたの元の問題が何であるかはわかりませんが、ハッシュを使用することをお勧めします」と書いて、優れた知恵を示しました。</p>

以下も参照してください。

于 2010-02-16T19:29:05.790 に答える
1

Sinan Ünür さんの回答は確かに最高です。しかし、これは私の好奇心を刺激したので、(perldoc perlmod) を少し読んで、パッケージの名前空間にアクセスする方法として "package_name::" ハッシュについて学びました。

次のコードは、main:: パッケージのシンボル テーブルにレコードを追加します。

use strict;
my $name = "blah";
my $var = "sss";
$main::{$name} = \$var;

print "$main::blah\n";

これは「sss」を出力します。

ただし、「use strict」はまだだまされていないため、print ステートメントにパッケージ名を追加する必要がありました。私は探し続けます - use vars は現時点では機能していないようです。

于 2010-02-22T01:29:21.767 に答える