首页 > 解决方案 > arg 1 的类型必须是块或子 {}(不是子程序条目)

问题描述

以下 Python 代码演示了我想在 Perl 中执行的操作:

def runner(cmd, arg):
    print("runner:", arg)
    cmd()

def run_hooks1(arg):
    def work():
        print("work", arg)

    if (arg):
        work()
    else:
        runner(work, "hello")

run_hooks1(True)
run_hooks1(False)

输出:

work True
runner: hello
work False

我认为将它移植到 Perl 会很简单。所以我从这段代码开始:

sub runner(&$) {
    my $cmd = shift;
    my $arg = shift;
    print STDOUT "runner: $arg\n";
    &{$cmd}();
}

sub run_hooks1($) {
    my $arg = shift;

    sub work() {
        print STDOUT "work: $arg\n";
    }

    if ($arg) {
        work();
    } else {
        runner \&work, "hello";
    }
}

run_hooks1(0);
run_hooks1(1);

不幸的是,这会导致:

Variable "$arg" will not stay shared at test.pl line 17.
runner: hello
work: 0
work: 0

由于这个警告,我改写run_hooks如下:

sub run_hooks1($) {
    my $arg = shift;

    my $work = sub {
        print STDOUT "work: $arg\n";
    };

    if ($arg) {
        &{$work}();
    } else {
        runner &work, "hello";
    }
}

但现在我得到:

Type of arg 1 to main::runner must be block or sub {} (not subroutine entry) at test.pl line 23, near ""hello";"
Execution of test.pl aborted due to compilation errors.

我尝试了多种其他方法来通过work函数传递给runner但无济于事。

我错过了什么?

标签: perlfunctional-programming

解决方案


你试过了吗:

runner \&$work, "hello";

或者干脆停止使用原型并执行以下操作:

runner $work, "hello";

Perl 中的原型适用于当您想要某种类型的对子调用的神奇解析时,就像某些内置函数一样。它们不适合像其他语言那样仅用于参数检查。


推荐阅读