Perl将函数作为参数传递-未定义的子引用
我正在读马克·杰森·多米努斯(MarkJason Dominus)的《高阶Perl》一书,我被第一个例子所困扰。它围绕递归地解决河内塔问题展开,我的程序做得很好。问题是,本书通过重构代码开发了这个示例,在这里,solution函数采用另一个参数,而不是简单地打印解决方案正在做什么。这是一个函数,在我的例子中,它只是做同样的事情 问题是,我已经定义了辅助函数,并试图通过引用传递它,然后从主函数调用它,但是我得到了以下错误 无法在main.pl第86行将未定义的值用作子例程引用 此版本不将函数作为参数,并正确地解决了问题Perl将函数作为参数传递-未定义的子引用,perl,Perl,我正在读马克·杰森·多米努斯(MarkJason Dominus)的《高阶Perl》一书,我被第一个例子所困扰。它围绕递归地解决河内塔问题展开,我的程序做得很好。问题是,本书通过重构代码开发了这个示例,在这里,solution函数采用另一个参数,而不是简单地打印解决方案正在做什么。这是一个函数,在我的例子中,它只是做同样的事情 问题是,我已经定义了辅助函数,并试图通过引用传递它,然后从主函数调用它,但是我得到了以下错误 无法在main.pl第86行将未定义的值用作子例程引用 此版本不将函数作为参
#!/usr/bin/perl
use utf8;
use v5.26;
use strict;
use warnings;
sub SolveTowerOfHanoiProblem0 {
my ($n, $start, $end, $extra) = @_;
if ($n == 1) {
say "Move disk #$n from $start to $end.";
} else {
SolveTowerOfHanoiProblem0($n - 1, $start, $extra, $end);
say "Move disk #$n from $start to $end.";
SolveTowerOfHanoiProblem0($n - 1, $extra, $end, $start);
}
}
SolveTowerOfHanoiProblem0(3, 'A', 'C', 'B');
输出:
Move disk #1 from A to C.
Move disk #2 from A to B.
Move disk #1 from C to B.
Move disk #3 from A to C.
Move disk #1 from B to A.
Move disk #2 from B to C.
Move disk #1 from A to C.
我希望重构代码,使输出每个步骤中发生的事情的行独立于解决方案代码,因此目前我编写了另一个函数,它只做同样的事情,但作为参数由调用方传递:
sub SolveTowerOfHanoiProblem {
my ($n, $start, $end, $extra, $moveDisk) = @_;
if ($n == 1) {
$moveDisk->($n, $start, $end);
} else {
SolveTowerOfHanoiProblem($n - 1, $start, $extra, $end);
$moveDisk->($n, $start, $end);
SolveTowerOfHanoiProblem($n - 1, $extra, $end, $start);
}
}
sub PrintInstruction {
my ($disk, $start, $end) = @_;
say "Move disk #$disk from $start to $end.";
}
SolveTowerOfHanoiProblem(8, 'A', 'C', 'B', \&PrintInstruction);
我遇到以下运行时错误:无法在main.pl第86行使用未定义的值作为子例程引用。这是我第一次调用传入函数的地方
第86行:
if ($n == 1) {
$moveDisk->($n, $start, $end); # <---- Here, Line 86
} else {
SolveTowerOfHanoiProblem($n - 1, $start, $extra, $end);
$moveDisk->($n, $start, $end);
我不明白为什么子引用是未定义的。我已经定义了我引用的函数,从目前为止我发现的情况来看,我似乎正确地调用了该函数
我也看过了,但是我的PrintInstruction函数不是在模块中定义的,它是在本地定义的,所以如果我理解正确,我不需要引用中的$symbol
我遗漏了什么?SolveTowerOfHanoipProblem函数需要一个code ref作为最后五个参数,但在«else»块中调用它时,您没有传递它:
SolveTowerOfHanoiProblem($n - 1, $start, $extra, $end);
应写为:
SolveTowerOfHanoiProblem($n - 1, $start, $extra, $end, $moveDisk);
您将代码引用传递给SolveTowerOfHanoipProblem的原始调用,而不是递归调用 您只需传递代码ref
SolveTowerOfHanoiProblem($n - 1, ..., $moveDisk);
或者可以消除反复传递相同值的需要
sub SolveTowerOfHanoiProblem {
my $moveDisk = pop;
local *helper = sub {
my ($n, $start, $end, $extra) = @_;
if ($n == 1) {
$moveDisk->($n, $start, $end);
} else {
helper($n - 1, $start, $extra, $end);
$moveDisk->($n, $start, $end);
helper($n - 1, $extra, $end, $start);
}
};
helper(@_);
}
相同,但使用Perl 5.16中引入的功能:
use feature qw( current_sub );
sub SolveTowerOfHanoiProblem {
my $moveDisk = pop;
sub {
my ($n, $start, $end, $extra) = @_;
if ($n == 1) {
$moveDisk->($n, $start, $end);
} else {
__SUB__->($n - 1, $start, $extra, $end);
$moveDisk->($n, $start, $end);
__SUB__->($n - 1, $extra, $end, $start);
}
}->(@_);
}
哇,真不敢相信我错过了。非常感谢,我很感激哇,我没有遇到像这样的嵌套子例程,谢谢你的提醒只是不要嵌套命名的子例程