arg 1的类型必须是block或sub {}(不是子例程条目)

jos*_*sch 2 perl functional-programming

以下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)
Run Code Online (Sandbox Code Playgroud)

输出:

work True
runner: hello
work False
Run Code Online (Sandbox Code Playgroud)

我认为把它移植到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);
Run Code Online (Sandbox Code Playgroud)

不幸的是,这会导致:

Variable "$arg" will not stay shared at test.pl line 17.
runner: hello
work: 0
work: 0
Run Code Online (Sandbox Code Playgroud)

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

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

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

    if ($arg) {
        &{$work}();
    } else {
        runner &work, "hello";
    }
}
Run Code Online (Sandbox Code Playgroud)

但现在我得到了:

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.
Run Code Online (Sandbox Code Playgroud)

我尝试了多种其他方式来传递work函数,runner但无济于事.

我错过了什么?

yst*_*sth 5

你试过了吗:

runner \&$work, "hello";
Run Code Online (Sandbox Code Playgroud)

或者只是停止使用原型并执行:

runner $work, "hello";
Run Code Online (Sandbox Code Playgroud)

Perl中的原型适用于你想要某种类型的神奇解析你的sub的调用,比如一些内置的get.它们不适用于其他语言的参数检查.