2013-02-01 24 views
0

我發現在perl中分派很多函數的最快方法是使用函數引用。 剩下的問題是,我必須將函數名稱包含在調度程序和函數模塊中的我們的($ func1,$ func2,...)列表中。我不能以任何方式包含它們,就像C包括會做的那樣。在這裏我的代碼: 主要模塊:在perl中調度函數,如何包含我們的列表

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 

在此先感謝提示。

+0

第一個模塊名爲enhufh1.pl,第二個模塊(dispatcher)是disph1.pl,第三個模塊(功能模塊)是fut1h1.pl。 – eleonora

+2

*永遠不要*使用子程序原型,除非你確切地知道他們做了什麼。你當然不需要他們 - 'sub dispatch {...}'很好。 – Borodin

回答

1

您確實應該使用Perl模塊 - *.pm文件 - 並將它們包括在需要use的地方。使這些模塊的子類Exporter允許它們將變量和子程序名稱導出到調用包中。

看看這三個來源的集合,這也對您的原始代碼添加了一些改進。

注意,你可以用它代替@EXPORT_OK@EXPORT陣列,在這種情況下,相應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; 

/家庭/ EN/DTEST/perl的/ forditas/UTF8/forditas/TEST1 /調度。下午

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/en/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 
+0

非常感謝,您的解決方案非常好,因爲我不必修改我的子例程。你的解決方案比我的解決方案執行效率高10%我仍然覺得難看,我必須在Utils.pm和dispatcher.pm中聲明函數名稱。我有大約800個函數名,它們的聲明使模塊不容易閱讀。 – eleonora

+0

@eleonora:正如我在我的回答中指出的那樣,如果您在'Utils'中使用'@ EXPORT'而不是'@ EXPORT_OK',則可以在'Dispatcher'中只使用'Utils',它會將所有內容導入到該列表中。但它被認爲是不好的做法,因爲'Dispatcher'中沒有任何東西可以說明已導入的符號。 – Borodin

+0

@eleonora:請注意'@ EXPORT'和'@ EXPORT_OK'的行爲與普通的數組相同,所以如果你的子例程有一些共同點,你可以在一個循環中構建它們。例如,在上面的代碼中,您可以編寫'我們的@EXPORT = map'sub $ _「,1..5' – Borodin

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($_); 
} 

使用函數調用來設置調度功能比出口一堆的變數,我的腦海裏更好。

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>; 

... 

如果您只是想使用「索引」通用名稱,您確實不需要「名稱」。把它們放在一個列表中。

相關問題