Perl调用存在于数组中的子例程

时间:2012-01-20 02:11:49

标签: perl

我正在尝试在Perl中创建一个状态机。为此,我有一个由statenames索引的数组。我可以把subs放到这个数组中。像这样:

   use constant {
    stInit          => 0,
    stHeader        => 1,
    stSalesHeader   => 2,
    stCatagory      => 3,
    stData          => 4,
    stTotal         => 5,
    stError         => 6, 
};

my $state = stInit;
my @actions;

$actions[stInit] = [sub{logState("Initial state entered",2) }];
$actions[stHeader] = [sub{logState("Header state entered",2) }];
$actions[stSalesHeader] = [sub{logState("Sales header state entered",2) }];
$actions[stCatagory] = [sub{logState("Category state entered",2) }];
$actions[stData] = [sub{logState("Data state entered",2) }];
$actions[stTotal] = [sub{logState("Total state entered",2) }];

但是我不知道如何调用子程序。我试过这个

$actions[$state]

但这似乎不起作用。这可能还是完全关闭?

5 个答案:

答案 0 :(得分:9)

你真的应该添加

use strict;
use warnings;

到代码的开头,会发现很多简单的错误。在这种情况下,您的代码很好,您可以使用

调用子例程
$actions[$state][0]();

但是没有必要将子例程放在方括号中,它只是创建一个单元素的匿名数组并添加一个额外的索引级别(因此在上面的代码行中为[0]。如果你写的话像这样的代码

$actions[stInit] = sub { logState("Initial state entered", 2) };

然后你就可以用

调用子程序了
$actions[$state]();

答案 1 :(得分:2)

稍微不同的是,您是否考虑过使用FSA::Rules来编写状态机?它相当强大,具有可选的GraphViz输出,使状态机更容易编写。

答案 2 :(得分:1)

从引用中调用子例程:

&{$actions[$state]}();

但是,根据您的代码,@actions不包含子例程引用,而是对子例程声明的数组引用。

首先,按照惯例声明潜艇,然后构建@actions:

$actions[0] = \&stInit;
$actions[1] = \&stHeader;
...and so on

答案 3 :(得分:1)

你应该这样做:

&{$actions[$state][0]}

但我不确定你为什么使用数组...如果你只有1个功能那么

$actions[stData] = sub{ ... }
...
&{$actions[$state]}

会奏效。如果你真的想要执行许多函数并使用数组,那么你可以这样做:

map { &{$_}  } @{$actions[$state]};

答案 4 :(得分:1)

删除方括号

删除无关的匿名数组创建
$actions[stInit] = sub{logState("Initial state entered",2) };

然后,您可以使用

调用该操作
$actions[stInit]();

如果您将某个操作存储在变量中,例如

my $action = $actions[$actionID];

然后你需要更多的语法才能让它实际进行调用

$action->();

然后再次,您可以使用哈希而不是数组

my %actions = (
    stInit        => sub { logState("Initial state entered",2) },
    stHeader      => sub { logState("Header state entered",2) },
    stSalesHeader => sub { logState("Sales header state entered",2) },
    stCatagory    => sub { logState("Category state entered",2) },
    stData        => sub { logState("Data state entered",2) },
);

这将使您不必在顶部设置常量。然后,您可以使用

调用操作
$actions{$state}();