I want to do something like this in Perl:
我想在Perl中做这样的事情:
$Module1="ReportHashFile1"; # ReportHashFile1.pm
$Module2="ReportHashFile2"; # ReportHashFile2.pm
if(Condition1)
{
use $Module1;
}
elsif(Condition2)
{
use $Module2;
}
ReportHashFile*.pm contains a package ReportHashFile* .
ReportHashFile * .pm包含一个包ReportHashFile *。
Also how to reference an array inside module based on dynamic module name?
如何根据动态模块名称引用模块内部的数组?
@Array= @$Module1::Array_inside_module;
Is there anyway I can achieve this. Some sort of compiler directive?
无论如何我能做到这一点。某种编译器指令?
3 个解决方案
#1
23
You might find the if
module useful for this.
您可能会发现if模块对此有用。
Otherwise the basic idea is to use require
, which happens at run-time, instead of use
, which happens at compile-time. Note that '
否则,基本思想是使用require,它在运行时发生,而不是在编译时发生。注意 '
BEGIN {
my $module = $condition ? $Module1 : $Module2;
my $file = $module;
$file =~ s[::][/]g;
$file .= '.pm';
require $file;
$module->import;
}
As for addressing globals, it might be easier if you just exported the variable or a function returning it to the caller, which you could use by its unqualified name. Otherwise there's also the possibility of using a method and calling it as $Module->method_name
.
至于寻址全局变量,如果您只是导出变量或将函数返回给调用者,可能会更容易,您可以通过其非限定名称使用它。否则,也可以使用方法并将其作为$ Module-> method_name调用。
Alternatively, you could use symbolic references as documented in perlref
. However, that's usually quite a code smell.
或者,您可以使用perlref中记录的符号引用。然而,这通常是代码味道。
my @array = do {
no strict 'refs';
@{ ${ "${Module}::Array_inside_module" } };
};
#2
8
Unless the execution speed is important, you can use string eval:
除非执行速度很重要,否则可以使用字符串eval:
if (Condition1) {
eval "use $Module1"; die $@ if $@;
}
elsif (Condition2) {
eval "use $Module2"; die $@ if $@;
}
#3
5
People have already told you how you can load the module with Perl primitives. There's also Module::Load::Conditional.
人们已经告诉过你如何使用Perl原语加载模块。还有Module :: Load :: Conditional。
If you're looking to access an array of the same name no matter which module you loaded, consider making a method for that so you can skip the symbolic reference stuff. Give each module a method of the same name:
如果你想要访问一个同名的数组,无论你加载哪个模块,考虑为它制作一个方法,这样你就可以跳过符号引用的东西。为每个模块提供一个相同名称的方法:
package ReportHashFileFoo;
our @some_package_variable;
sub get_array { \@some_package_variable }
Then, when you load that module:
然后,当您加载该模块时:
if( ... some condition ... ) {
eval "use $module" or croak ...;
my $array_ref = $module->get_array;
}
I don't know what you're really doing (XY Problem), but there's probably a better design. When things seem tricky like this, it's usually because you're overlooking a better way to to it.
我不知道你在做什么(XY问题),但可能有更好的设计。当事情看起来像这样棘手时,通常是因为你忽视了一种更好的方法。
#1
23
You might find the if
module useful for this.
您可能会发现if模块对此有用。
Otherwise the basic idea is to use require
, which happens at run-time, instead of use
, which happens at compile-time. Note that '
否则,基本思想是使用require,它在运行时发生,而不是在编译时发生。注意 '
BEGIN {
my $module = $condition ? $Module1 : $Module2;
my $file = $module;
$file =~ s[::][/]g;
$file .= '.pm';
require $file;
$module->import;
}
As for addressing globals, it might be easier if you just exported the variable or a function returning it to the caller, which you could use by its unqualified name. Otherwise there's also the possibility of using a method and calling it as $Module->method_name
.
至于寻址全局变量,如果您只是导出变量或将函数返回给调用者,可能会更容易,您可以通过其非限定名称使用它。否则,也可以使用方法并将其作为$ Module-> method_name调用。
Alternatively, you could use symbolic references as documented in perlref
. However, that's usually quite a code smell.
或者,您可以使用perlref中记录的符号引用。然而,这通常是代码味道。
my @array = do {
no strict 'refs';
@{ ${ "${Module}::Array_inside_module" } };
};
#2
8
Unless the execution speed is important, you can use string eval:
除非执行速度很重要,否则可以使用字符串eval:
if (Condition1) {
eval "use $Module1"; die $@ if $@;
}
elsif (Condition2) {
eval "use $Module2"; die $@ if $@;
}
#3
5
People have already told you how you can load the module with Perl primitives. There's also Module::Load::Conditional.
人们已经告诉过你如何使用Perl原语加载模块。还有Module :: Load :: Conditional。
If you're looking to access an array of the same name no matter which module you loaded, consider making a method for that so you can skip the symbolic reference stuff. Give each module a method of the same name:
如果你想要访问一个同名的数组,无论你加载哪个模块,考虑为它制作一个方法,这样你就可以跳过符号引用的东西。为每个模块提供一个相同名称的方法:
package ReportHashFileFoo;
our @some_package_variable;
sub get_array { \@some_package_variable }
Then, when you load that module:
然后,当您加载该模块时:
if( ... some condition ... ) {
eval "use $module" or croak ...;
my $array_ref = $module->get_array;
}
I don't know what you're really doing (XY Problem), but there's probably a better design. When things seem tricky like this, it's usually because you're overlooking a better way to to it.
我不知道你在做什么(XY问题),但可能有更好的设计。当事情看起来像这样棘手时,通常是因为你忽视了一种更好的方法。