2017-12-02 295 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

相关问题