0

perl で多くの関数をディスパッチする最速の方法は、関数参照を使用することであることがわかりました。残りの問題は、ディスパッチャーと関数モジュールの両方で、関数名を ($func1, $func2, ...) リストに含めなければならないことです。C の include のように、それらをインクルードする方法を見つけることができませんでした。ここに私のコード: メインモジュール:

use strict;
our ($base);

$base = '/home/en/dtest/perl/forditas/utf8/forditas/test1';
require("$base/disph1.pl");
require("$base/fut1h1.pl");


for (my $j = 0; $j < 5; $j++){
   dispatch($j);
}

ディスパッチャ モジュール:

use strict;
our ($base);
require("$base/fut1h1.pl");

our ($sref1, $sref2, $sref3, $sref4, $sref5);  # This is what I'd like to include

my %shash = (
   '0' => $sref1,
   '1' => $sref2,
   '2' => $sref3,
   '3' => $sref4,
   '4' => $sref5,
);

sub dispatch($){
  my ($ix) = @_;
  my ($a, $b, $c);
  $a = 1; $b = 2; $c = 3;
  my $ref = $shash{$ix};
  &$ref($a,$b, $c);
}

1;

機能モジュール:

use strict;

our ($sref1, $sref2, $sref3, $sref4, $sref5);   # This is what I'd like to include

$sref1 = sub($$$) { 
   my ($a,$b,$c) = @_;
   print "sub1 $a,$b,$c\n"; 
};
$sref2 = sub($$$) { my ($a,$b,$c) = @_; print "sub2 $a, $b, $c\n"; };
$sref3 = sub {  print "sub3\n"; };
$sref4 = sub {  print "sub4\n"; };
$sref5 = sub {  print "sub5\n"; };

1;

これは実行の結果です:

$ perl enhufh1.pl
sub1 1,2,3
sub2 1, 2, 3
sub3
sub4
sub5

ヒントを事前にありがとう。

4

3 に答える 3

1
  • まず、整数を要素にマッピングすることは、ハッシュの誤用です。配列を使用することもできます。

  • 次に、アルゴリズムを実装から分離して、メイン スクリプトに結合したいようです。これは称賛に値しますが、関数モジュールが何に使用されているかを知っていることは明らかです。したがって、一種のナレッジ グラフを導出する場合、最も単純なケースは、汎用モジュールがディアパッチ モジュールを認識していることです。

この目的のためにヘルパー関数を作成するだけです:

use strict;
use warnings;

our @EXPORT_OK = qw<setup_dispatch dispatch>;
use parent 'Exporter';

my @dispatch_subs;
sub setup_dispatch { @dispatch_subs = @_; }

sub dispatch { 
    my ($a, $b, $c) = ( 1, 2, 3 );
    return $dispatch_subs[shift()]->( $a, $b, $c );
}

これで、汎用モジュールがセットアップ機能を呼び出すことができます。

use strict;
use warnings;
use Dispatch ();

Dispatch::setup_dispatch( 
  # I echo the caution about using prototypes
  sub ($$$) {   
     my ($a,$b,$c) = @_;
     print "sub1 $a,$b,$c\n"; 
  }
, sub ($$$) { my ($a,$b,$c) = @_; print "sub2 $a, $b, $c\n"; }
, sub {  print "sub3\n"; }
, sub {  print "sub4\n"; }
, sub {  print "sub5\n"; }
);

そして、次のようにメインモジュールで両方を使用するだけです:

use strict;
use warnings;
require 'plugin_functions.pl';

use Dispatch qw<dispatch>;

...

「インデックス付き」の一般的な名前を使用したいだけであれば、「名前」は本当に必要ありません。それらをリストに入れるだけです。

于 2013-02-01T14:13:47.683 に答える
1

Perl モジュール (*.pmファイル) を使用し、必要な場所にそれらを含める必要がありuseます。これらのモジュールを のサブクラスにExporterすることで、変数と aubroutine の名前を呼び出し元のパッケージにエクスポートできます。

この 3 つのソースのセットを見てみましょう。これにより、元のコードにいくつかの改善が加えられます。

@EXPORTの代わりに配列を使用できることに注意してください。その@EXPORT_OK場合、対応するuseステートメントは、インポートするシンボルをリストする必要はありません。ただし、使用時にシンボルをリストする方が適切です。そうでない場合は、モジュールのコードを調べて、インポートされているものを正確に検出する必要があります。

main.pl

use strict;
use warnings;

use lib '/home/en/dtest/perl/forditas/utf8/forditas/test1';

use Dispatcher qw/ dispatch /;

dispatch($_) for 0 .. 4;

/home/en/dtest/perl/forditas/utf8/forditas/test1/Dispatcher.pm

package Dispatcher;

use strict;
use warnings;

require Exporter;
our @ISA = qw/ Exporter /;
our @EXPORT_OK = qw/ dispatch /;

use Utils qw/ sub1 sub2 sub3 sub4 sub5 /;

my @dtable = ( \&sub1, \&sub2, \&sub3, \&sub4, \&sub5 );

sub dispatch {
  my ($i) = @_;
  my ($a, $b, $c) = (1, 2, 3);
  $dtable[$i]($a, $b, $c);
}

1;

/home/ja/dtest/perl/forditas/utf8/forditas/test1/Utils.pm

package Utils;

use strict;
use warnings;

require Exporter;
our @ISA = qw/ Exporter /;
our @EXPORT_OK = qw/ sub1 sub2 sub3 sub4 sub5 /;

sub sub1 { 
   my ($a, $b, $c) = @_;
   print "sub1 $a,$b,$c\n"; 
}

sub sub2 {
  my ($a, $b, $c) = @_;
  print "sub2 $a, $b, $c\n";
}

sub sub3 {
  print "sub3\n";
}

sub sub4 {
  print "sub4\n";
}

sub sub5 { 
  print "sub5\n";
}

1;

出力

sub1 1,2,3
sub2 1, 2, 3
sub3
sub4
sub5
于 2013-02-01T11:50:00.670 に答える
0

必要なのはExporter.

モジュール内:

require Exporter;

@EXPORT = qw($sref1 $sref2 $sref3);

ただし、別の設計を検討する価値があるかもしれません。

脚本:

set_dispatch(0,sub{ .... });

ディスパッチャ モジュール:

my @dispatch;  #If just indexing to numbers, use an array instead of a hash.

sub set_dispatch {
    $dispatch[$_[0]] = $_[1];
}

メインモジュール:

for (0..4)    #equivalent to before, but more Perlish.
{
   dispatch($_);
}

私の考えでは、関数呼び出しを使用してディスパッチ関数を設定する方が、一連の変数をエクスポートするよりも優れています。

于 2013-02-01T11:23:13.100 に答える