Тип аргумента 1 должен быть block или sub {} (не вход подпрограммы) - PullRequest
0 голосов
/ 20 февраля 2019

следующий код 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, но безрезультатно.

Чего мне не хватает

1 Ответ

0 голосов
/ 20 февраля 2019

Вы пробовали:

runner \&$work, "hello";

Или просто прекратите использовать прототипы и выполните:

runner $work, "hello";

Прототипы в Perl предназначены для тех случаев, когда вам нужен какой-то магический разбор вызовов для вашегосаб, как некоторые встроенные получают.Они плохо подходят для простой проверки параметров, как это делают другие языки.

...