2

test1 と test2 の 2 つのモジュールがあり、それらのサブルーチンを順番に実行する必要があります。同じ変数 $var を変更する必要があり、外側のスクリプトは最終結果を出力する必要があります。残念ながらこれは機能せず、このSO Questionと非常によく似ているようです。

#test1.pm
use strict;
package test1;
my $var;
sub step1 {
  $var = "Hello";
}
1;

#test2.pm
use strict;
package test2;
my $var;
sub step1 {
    $var = $var." World!\n";
}
1;

#execTests.pl
use strict;
require test1;
require test2;
&test1::step1;
&test2::step1;
print $test2::var;

$var を必要な両方のパッケージの同じスコープに含めるにはどうすればよいですか?

4

3 に答える 3

1

これがBADBADBAD DESIGNであるという明白な免責事項を使用すると、グロブを簡単に利用できます。

==> exec.pl <==
#!/usr/bin/perl
use strict;
use warnings;
# You can omit this line, but there will be a warning about $My::Var being used only once
$My::Var = undef;
require 's1.pl';
require 's2.pl';
print $My::Var . "\n";

==> s1.pl <==
$My::Var = "Hello";


==> s2.pl <==
$My::Var .= "World";

グロブは基本的にパッケージスタッシュのエントリです。パッケージ変数とサブルーチンは、パッケージスタッシュ内にあります。スタッシュエントリはグロブと呼ばれます。

http://perldoc.perl.org/perlguts.html#Stashes-and-Globs

隠し場所とグロブが比較的単純であり、それらを操作しやすいことは、Perlを本当にクールにしていることの1つだと思います。

于 2012-09-20T18:33:07.557 に答える
1

主な問題は、で宣言された変数はmyパッケージ変数ではなく、パッケージ名で完全修飾してもアクセスできないことです。ただし、代わりに を使用してパッケージ変数を宣言したour場合でも、引き続きtest1.pm参照execTests,plし、$test1::varwhiletest2.pmを使用して作業しています$test2::var

代わりに、メイン プログラムに対してローカルな変数を使用し、それを 2 つのステップに渡して変更することをお勧めします。

このようなもの(テスト済みで動作中)

test1.pm

use strict;
use warnings;

package test1;

use parent 'Exporter';
our @EXPORT = qw/step1/;

sub step1 {
  $_[0] = "Hello";
}

1;

test2.pm

use strict;
use warnings;

package test2;

use parent 'Exporter';
our @EXPORT = qw/step2/;

sub step2 {
    $_[0] .= " World!\n";
}

1;

execTests.pl

use strict;
use warnings;

use test1;
use test2;

my $var;

step1($var);
step2($var);

print $var;

出力

Hello World!
于 2012-09-20T20:07:20.720 に答える
1

私の知る限り、2 つの変数が常に同じ値を共有することはできません。ここにあなたを助けることができるいくつかのアイデアがあります:

パッケージ変数:

{
   package test1;
   our $var;
   sub step1 {$var = "Hello"}
}
{
  package test2;
  our $var;
  sub step1 {$var .= " World!\n"}
}

test1::step1();
$test2::var = $test1::var;
test2::step1();

print $test2::var;

コメント: 醜い

参考文献:

{
  package test1;
  our $varref;
  sub init {
    my ($ref) = @_;
    $varref = $ref;
  }
  sub step1 {$$varref = "Hello"}
}
{
  package test2;
  our $varref;
  sub init {
    my ($ref) = @_;
    $varref = $ref;
  }
  sub step1 {$$varref .= " World!\n"}
}

my $var = "";
test1::init(\$var);
test2::init(\$var);

test1::step1();
test2::step1();

print $var;

コメント: より良いですが、より多くのコードが必要です。

追加の共有モジュール:

{
  package test::shared;
  our $var;
}
{
  package test1;
  sub step1 {$test::shared::var = "Hello"}
}
{
  package test2;
  sub step1 {$test::shared::var .= " World!\n"}
}

test1::step1();
test2::step2();
print $test::shared::var;

コメント: いくつかの利点があります。

明示的な状態

{
  package test1;
  sub step1 {
    my $state = @_;
    $state->{var} = "Hello";
    return $state;  # superfluous, but helps understanding
  }
}
{
  package test2;
  sub step1 {
    my $state = @_;
    $state->{var} .= " World!\n";
    return $state;  # superfluous, but helps understanding
  }
}

my $state = {};

$state = test1::step1($state);  # equiv: test1::step1($state), because of references
$state = test2::step1($state);

print $state->{var};

コメント: これはほとんどオブジェクト指向プログラミングです。何をいつ共有するかが明示されているので、私はこのパターンを好みます。明示的な状態により、マルチスレッドと再入可能性の観点から、アプリケーションのスケーリングが容易になります。

コスト: 明示性。詳細な構文。

利点: 再入可能性、明示性による明確な一連の思考。

于 2012-09-20T17:59:43.930 に答える