【发布时间】:2015-08-03 14:07:58
【问题描述】:
我有一些行为相当奇怪的代码。
我在一个函数内部,我声明了一个嵌套函数,它应该检查是否有问题。如果不是,那么它应该休眠五秒钟,然后再次调用自己。
sub stop {
sub wait_for_stop {
my $vm_view = shift;
if ( $vm_view->runtime->powerState->val ne "poweredOff" ) {
debug("...");
sleep(5);
wait_for_stop();
}
}
debug("Waiting for the VM to stop");
wait_for_stop( @$vm_views[0] );
}
因此,在导致if 条件内递归的调用中,如果我输入参数(如函数定义所期望的那样),如下所示:
wait_for_stop($vm_view);
我得到一个无限循环。
如果我不带参数,就像上面的代码示例一样,它会按预期工作。
后续调用中的$vm_view不应该为空吗?还是最后使用的值 ($vm_view->runtime->powerState->val)?这两种情况都会导致意外的行为和错误。
但它可以在没有任何参数的情况下工作。那为什么呢? perldoc 有什么我遗漏的吗?
EDIT1: 实际上,$vm_views 的值确实发生了变化,所以这不是无限循环的原因。
一般说明
我正在使用 VMware SDK。 $vm_views 对象包含 VM 详细信息。我正在轮询它的一种方法来检测变化,在这种特殊情况下,我需要知道机器何时关闭。所以,由于没有更好的方法,我每 5 秒打一次电话,直到数值满意为止。
我的目的是停止虚拟机,进行只能在关闭时进行的修改,然后启动它。
实际问题
当我不传递参数时,该块按预期工作——它会等到值是poweredOff(VM 关闭),然后继续,至少对我来说没有多大意义。
如果我将$vm_view 作为参数,我会得到一个无限循环(值仍然会改变,因为我正在调用一个方法)。
所以我想知道为什么该函数有效,第一次调用后,$vm_view 应该是undef,因此会陷入无限循环? [undef ne "poweredOff" -> sleep -> 递归直到死亡]
为什么,当我通过期望值时,它会卡住?
PS:对于那些说我的递归在这种情况下很奇怪和无用的人——由于种种原因,我需要使用这种格式(它更适合我的需要,因为在我开始工作之后,我将对其进行修改以添加各种东西并重用它,而且,就我的想法而言,函数似乎是最好的选择)。
【问题讨论】:
-
“它按预期工作”这是否意味着当你不传入参数时它不会给出无限循环?
-
你能提供一个MCVE,也许还有一个简单的嘲笑
$vm_view? -
这是递归的一种奇怪用法。我认为
while ($val ne "poweredOff") { sleep 5; }一目了然更容易理解,并且您不必担心深度递归警告或进栈。 (当然,你必须用$val实际做 一些事情,否则你会得到一个无限循环,无论你使用递归还是迭代。) -
"undef ne "poweredOff" -> sleep -> recursion until death" 这不是发生的事情。
$vm_view的值为undef,但您尝试调用其runtime方法。在接近比较之前,Can't call method "runtime" on an undefined value将立即失败。这不能是您正在运行的代码 -
关于递归的选择,请相信我是错误的选择。有总是一种避免递归的方法,这里它只是代表
while循环。每次递归过程调用自己时,都会用完另一个堆栈帧,如果等待时间过长,您就有可能遇到OUT OF MEMORY!错误,这将杀死您的程序。除了难以阅读之外,而且(正如您所发现的)难以正确理解
标签: perl recursion while-loop vmware