我不太讓你想什麼,而是你可以隨時讓您的插頭可插拔:
我們有一個分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
設置。
如果你喜歡傳遞名字而不是coderefs,我們也可以安排。
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)
表示,這是適用於子程序一個屬性。我們只需要兩個參數,我們想要註解的子程序的全名以及子程序的coderef。
然後,我們關閉一部分的嚴格性來重新定義子${$glob}
。這有點高級,但它實質上只是訪問內部符號表。
我們用上面給出的process_file
的虛擬版本替換帶註釋的子版本。我們可以傳遞所有參數(@_
),而不需要進一步處理。
畢竟,我們一個小豆蔻資料片添加到您之前使用的替補:
sub process_type_A :file_processor {
print "I can haz $counter\n";
}
...它只是沒有做進一步的修改替換。使用庫時這些更改是不可見的。我意識到這種方法的限制,但在編寫普通代碼時不太可能碰到它們。
您可以從第一個子程序中調用第一個子程序(在完成第一個子程序中的所有錯誤處理後)。或者,您可以使用全局標誌,第二個子標籤將檢查第一個子標籤是否成功運行。或者,您可以將第一個子標識作爲參數之一傳遞給第二個子標識。 TIMTOWTDI! :) – 2012-09-10 20:08:31
問題是我需要第一個子返回計數器,以便我的腳本可以使用計數器處理和輸出文件。在完成處理數據之前,我無法調用第二個更新文件。如果第一個腳本在腳本中被調用,而第二個腳本中的某個點沒有被調用,我想拋出一個錯誤。我不能在第二個測試,因爲如果它測試一個全局變量,這意味着第二個被調用,從而使全局變量測試沒有意義。 – MitchelWB