例如,下面给出了伪代码。根据给 x 的输入,如果 x 是 func1,则必须调用 func1()。如果 x 是 func2,则必须调用 func2()。有没有办法做到这一点。我不想使用 if 或 switch case 语句。有没有其他方法可以根据用户输入进行函数调用?(类似于将函数视为变量?
sub func1()
{...}
sub func2()
{...}
sub mainfunc()
{
x = <STDIN>;
x();
}
Run Code Online (Sandbox Code Playgroud)
看起来您正在寻找调度表
use warnings;
use strict;
use feature 'say';
my %option = (
o1 => sub { say "Code for func1, to run for key 'o1'"; },
o2 => sub { say "Code that should run for input 'o2'"; },
#...
);
my $input = <STDIN>;
chomp $input;
# Dereference the code-reference (run code) associated with $input value
$option{$input}->();
Run Code Online (Sandbox Code Playgroud)
这里sub { ... }
定义了一个匿名子程序并返回对代码的引用。获取代码引用的另一种方法是获取命名子的引用,语法为\&sub-name
。作为引用,它是(单值)标量类型,因此可以用作哈希值。
因此,当用户提供o1
运行的是引用 ( sub { ... }
) 中的代码时,它是o1
散列中键的值,即$option{o1}
.
运行代码引用的语法很像取消引用数组或散列引用
$ar->[0] # dereference array reference, for the first element
$hr->{key} # dereference hash reference, for value for key 'key'
$cr->(LIST) # dereference code reference, to run with arguments in LIST
Run Code Online (Sandbox Code Playgroud)
$cr
此处的标量变量将具有代码引用my $cr = sub { ... }
.
安全的方法是将名称散列映射到子程序,这样恶意用户就无法调用任意子程序。就像是:
my %table = ("func1" => \&func1, "func2" => \&func2);
my $x = <STDIN>;
chomp $x;
if (exists $table{$x}) {
$table{$x}->();
} else {
# Handle error
}
Run Code Online (Sandbox Code Playgroud)