2017-12-02 294 views
2

假設我有一個功能foo(或::foo,或者main::foo如果你喜歡),我定義如何通過符號表來訪問子主::和子的名字在一個標量

use strict; 
my $sub_name = 'foo'; 

我想間接調用foo,因爲「名稱存儲在$sub_name中的函數」。 (對於這個例子來說,假設調用應通過列表1, 2, 3作爲參數。)

我知道,有一種方法用符號表工作main::直接,對待它就像一個散列做到這一點像數據結構一樣。

這個符號表的咒語就是我要找的。

我以前做過很多次這樣的事情,但我多年沒有編寫過Perl,而且我不再記住這個咒語。

(我更願意這樣做,而不必訴諸no strict,但如果這是不可能根本不算什麼。)

+0

可能的重複:https://stackoverflow.com/q/1915616/5830574 – PerlDuck

+0

@PerlDuck:我看到了這個線程,但我沒有看到答案我的問題在裏面。 – kjo

回答

3

我會簡單地用一個象徵性的參考。

my $sub = \&$qualified_sub_name; # \&$symbol is except from strict 'refs'. 

$sub->() 

但是您要求我們避免使用符號引用。這太複雜了。 (這可能也無法處理冒號的怪異,但合法的誤操作。)

my $pkg = \%::; 
my $sub_name = $qualified_sub_name; 
$pkg = $pkg->{$1} while $sub_name =~ s/^(.*?::)//sg; 
my $sub = $pkg->{$sub_name}; 
$sub = *{ $pkg->{$sub_name} }{CODE} 
    if ref(\$sub) eq 'GLOB'; # Skip if glob optimized away. 

$sub->() 
+1

你的答案慢跑了我的記憶。我正在尋找的僅僅是表達式'* {$ :: {'foo'}} {CODE}(1,2,3)'。謝謝! – kjo

+2

@ikegami不,如果沒有其他插槽(如'$ foo'或'@ foo')存在,perl會優化簡單子'foo'的情況。它會直接在符號表中存儲一個coderef。 – melpomene

+1

另一個有趣的例子是常量:'perl -wE'使用常量foo => 42;說$ :: {foo}' - 'SCALAR(0x3a9808)'。不是一團糟,只是標準的Perl行爲。 – melpomene

1

您可以使用can

my $sub_name = 'foo'; 
my $coderef = main->can($sub_name); 
$coderef->(@args); 

正如其他人所說,你要注意,這也可以返回如「能方法「或」isa「。 另外,如果$sub_name包含Some::Module::subname,這也將被調用。

如果您不確定$sub_name中有什麼,您可能需要採取不同的方法。 只有當您控制了$sub_name並且它只能包含預期值時,才能使用它。 (我認爲這,這就是爲什麼我寫這個答案。)

+0

如果'$ sub_name'是例如,這可能會返回意想不到的結果' 「ISA」'。 – melpomene

+0

OP詢問如何執行子呼叫,而不是方法呼叫(無論如何你都做錯了!!)。你的方法可能會導致錯誤的子被調用。 – ikegami

+0

ikegami:'$ coderef - >()'是一個子調用,不是方法調用。 – tinita

相關問題