调用定义为变量的子例程

时间:2018-07-12 12:26:16

标签: perl subroutine data-transfer

我正在开发一个程序,该程序在单独的文件中使用不同的子例程。

共有三个部分

  • 带有子例程名称的文本文件

  • 带有子例程的Perl程序

  • 提取子程序名称并启动它的主程序

该子例程从文本文件获取数据。

我需要用户选择文本文件,然后程序提取子例程的名称。

文本文件包含

cycle.name=cycle01

这是主程序:

# !/usr/bin/perl -w

use strict;
use warnings;

use cycle01;

my $nb_cycle = 10;

# The user chooses a text file

print STDERR "\nfilename: ";

chomp($filename = <STDIN>);

# Extract the name of the cycle 

open (my $fh, "<", "$filename.txt") or die "cannot open $filename";

while ( <$fh> ) {

    if ( /cycle\.name/ ) {

        (undef, $cycleToUse) = split /\s*=\s*/;
    }
}

# I then try to launch the subroutine by passing variables.
# This fails because the subroutine is defined as a variable.

$cycleToUse($filename, $nb_cycle);

这是另一个文件中的子例程

# !/usr/bin/perl

package cycle01;

use strict;
use warnings;

sub cycle01 {

    # Get the total number of arguments passed
    my ($filename, $nb_cycle) = @_;
    print "$filename, $nb_cycle";

2 个答案:

答案 0 :(得分:4)

您的代码无法编译,因为在最后一次调用中,您键入了$nb_cycle的名称。如果您发布实际运行的代码会很有帮助:-)

传统上,Perl模块名称以大写字母开头,因此您可能希望将软件包重命名为Cycle01

快速而肮脏的方法是使用字符串eval。但是评估包含代码的任意字符串是危险的,因此我不会向您展示。最好的方法是使用调度表-基本上是一个哈希,其中的键是有效的子例程名称,而值是对子例程本身的引用。最好的添加位置是在Cycle01.pm文件中:

our %subs = (
  cycle01 => \&cycle01,
);

然后,程序的结尾变为:

if (exists $Cycle01::subs{$cycleToUse}) {
  $Cycle01::subs{$cycleToUse}->($filename, $nb_cycle);
} else {
  die "$cycleToUse is not a valid subroutine name";
}

(请注意,在chomp()循环中读取行时,还需要while行。)

答案 1 :(得分:1)

要建立在Dave Cross的答案上,我通常避免使用哈希表,部分原因是在perl中,无论如何一切都是哈希表。取而代之的是,我所有的入口点子都以特定的前缀开头,该前缀取决于我在做什么,但是在这里,我们仅将ep_用作入口点。然后我做这样的事情:

my $subname = 'ep_' . $cycleToUse;
if (my $func = Cycle01->can($subname))
{
  $func->($filename, $nb_cycle);
}
else
{
  die "$cycleToUse is not a valid subroutine name";
}

can中的UNIVERSAL方法是从perl的哈希表中为我提取CODE引用的,而不是我自己维护(忘记更新它)。前缀使我可以在同一名称空间中拥有其他功能和方法,而这些功能和方法不能由用户代码直接调用,从而使我仍可以将代码重构为常用功能,等等。

如果您还想拥有其他名称空间,我建议将它们全部放在一个父名称空间中,并可能以相同的方式添加所有前缀,并且在理想情况下,禁止使用::或{{ 1}}(单引号)中,以便将用户可能调用的内容的范围最小化为​​仅愿意测试的范围。

例如

'

相反,这样做绝对有好处,例如明确要公开的内容。此处的优点是不必维护单独的列表。我总是很恐怖。