私はあなたが試していることを完全には理解していませんが、あなたはいつでもあなたの潜水艦をプラグイン可能にすることができます:
サブがありprocess_file
ます。これは、メイン処理を実行する引数としてサブルーチンを取ります。
our $counter;
sub process_file {
my ($subroutine, @args) = @_;
local $counter = get_counter();
my @return_value = $subroutine->(@args);
set_counter($counter);
return @return_value;
}
# Here are other sub definitions for the main processing
# They can see $counter and always magically have the right value.
# If they assign to it, the counter file will be updated afterwards.
サブがあると仮定すると、次のprocess_type_A
ことができます
my @return_values = process_file(\&process_type_A, $arg1, $arg2, $arg3);
process_type_A($arg1, $arg2, $arg3)
これは、追加の呼び出しスタックフレームと設定を除いて、と同じように動作し$counter
ます。
coderefの代わりに名前を渡すことを好む場合は、それも手配できます。
package MitchelWB::FileParsingLib;
our $counter;
our %file_type_processing_hash = (
"typeA" => \&process_type_A,
"typeB" => \&process_type_B,
"countLines" => sub { # anonymous sub
open my $fh, '<', "./dir/$counter.txt" or die "cant open $counter file";
my $lines = 0;
$lines++ while <$fh>;
return $lines;
},
);
sub process_file {
my ($filetype, @args) = @_;
local $counter = get_counter();
# fetch appropriate subroutine:
my $subroutine = $file_type_processing_hash{$filetype};
die "$filetype is not registered" if not defined $subroutine; # check for existence
die "$filetype is not assigned to a sub" if ref $subroutine ne 'CODE'; # check that we have a sub
# execute
my @return_value = $subroutine->(@args);
set_counter($counter);
return @return_value;
}
...;
my $num_of_lines = process_file('countLines');
編集:最もエレガントなソリューション
または:属性は本当にきれいです
なぜ愚かなコールバック?なぜ余分なコード?なぜ規約を呼び出すのですか?なぜテーブルをディスパッチするのですか?それらはすべて非常に興味深く柔軟ですが、よりエレガントなソリューションがあります。ほんの少しの情報を忘れていたのですが、今ではすべてがうまくいきました。Perlには、他の言語では「注釈」と呼ばれる「属性」があり、コードや変数に注釈を付けることができます。
新しいPerl属性の定義は簡単です。使用する属性と同じ名前のサブをuse Attribute::Handlers
定義します。
sub file_processor :ATTR(CODE) {
my (undef, $glob, $subroutine) = @_;
no strict 'refs';
${$glob} = sub {
local $counter = get_counter();
my @return_value = $subroutine->(@_);
set_counter($counter);
return @return_value;
}
この属性を使用して:ATTR(CODE)
、これがサブルーチンに適用可能な属性であることを示します。必要な引数は2つだけです。注釈を付けるサブルーチンのフルネームと、サブルーチンへのcoderefです。
次に、厳密性の一部をオフにして、サブを。で再定義し${$glob}
ます。これは少し高度ですが、基本的には内部シンボルテーブルにアクセスするだけです。
注釈付きのサブを、上記のようにダムダウンしたバージョンに置き換えprocess_file
ます。@_
さらに処理することなく、すべての引数()を直接渡すことができます。
その後、以前に使用した潜水艦に小さな情報を追加します。
sub process_type_A :file_processor {
print "I can haz $counter\n";
}
…そしてそれはそれ以上の変更なしでただ交換をします。ライブラリを使用する場合、変更は表示されません。私はこのアプローチの制限を認識していますが、通常のコードを書くときにそれらに遭遇する可能性はほとんどありません。