Perl 子程序是否可以强制其调用者返回? [英] Is it possible for a Perl subroutine to force its caller to return?

查看:51
本文介绍了Perl 子程序是否可以强制其调用者返回?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我有 Perl 模块

If I have Perl module like

 package X;

和一个像

 my $x = X->new ();

X.pm 中,我为 $x 编写了一个错误处理程序,称为 handle_error,我称之为

Inside X.pm, I write an error handler for $x called handle_error, and I call it

 sub check_size
 {
     if ($x->{size} > 1000) {
         $x->handle_error ();
         return;
     }
 }

有没有办法让 handle_error 强制从其调用程序返回?换句话说,在这个例子中,我可以让 handle_errorcheck_size 中做 return 而不实际在那里写 return 吗?

Is there any way to make handle_error force the return from its caller routine? In other words, in this example, can I make handle_error do return in check_size without actually writing return there?

推荐答案

在调用堆栈上回溯多个级别的唯一合理方法是抛出异常/死亡.

The only reasonable way to backtrack multiple levels up the call stack is by throwing an exception/dying.

也就是说,你真的应该重新考虑你想要做什么.一个程序员(包括你自己,六个月后)会期望,当一个函数调用完成时,它之后的语句将执行(除非抛出异常).违反该预期将导致在 handle_error 中引起的错误,但似乎与调用 handle_error 的代码有关,使它们极难调试.这不是一件好事.

That said, you really should reconsider what you want to do. A programmer (including yourself, six months from now) will expect that, when a function call completes, the statement after it will execute (unless an exception is thrown). Violating that expectation will cause bugs which are caused in handle_error, but appear to be with the code which called handle_error, making them extremely difficult to debug. This is Not A Good Thing.

您还假设绝对没有在处理错误后继续操作是合适的.对这样的假设进行硬编码实际上是一个确定的保证,一旦您有时间忘记它,您就会遇到在调用 handle_error 后需要继续的情况(然后浪费大量时间试图找出为什么 handle_error 之后的代码没有运行).

You're also making the assumption that there is absolutely no situation in which continuing after an error is handled will be appropriate. Hardcoding an assumption like that is practically a sure guarantee that, as soon as you've had time to forget it, you'll come across a case where you need to continue after calling handle_error (and then waste huge amounts of time trying to figure out why the code after handle_error doesn't get run).

然后假设您总是想要跳过调用堆栈中的恰好两级.这是另一个假设,一旦硬编码就会失败.不仅会出现调用代码应该继续的情况,还会出现需要在调用堆栈上向上三层的情况.

And then there's the assumption that you'll always want to skip back exactly two levels in the call stack. That's another assumption that will fail as soon as it's hardcoded. Not only will there be cases where the calling code should continue, there will also be cases where you need to go three levels up the call stack.

因此,只需通过调用 die 而不是 return 来让 handle_error 退出,并在应继续执行的适当级别捕获异常.您不知道将调用 sub 的每个位置,因此您无法预测它需要返回多少级.

So just have handle_error exit by calling die instead of return and trap the exception at the appropriate level where execution should continue. You don't know every place where the sub will ever be called, so you can't predict how many levels back it will need to go.

在手头的代码中,如果只是说 return 的额外行打扰你,你可以使用 return $x->handle_error; 你甚至可以得到摆脱封闭范围并使其 return $x->handle_error if $x->{size} >1000; 有 - 删除了三行而不是一行,加上一对大括号和两对括号作为免费奖励.

In the code at hand, if the extra line to just say return is bothering you, you can use return $x->handle_error; You can even get rid of the enclosing scope and make it return $x->handle_error if $x->{size} > 1000; There - three lines removed rather than just one, plus a pair of braces and two pairs of parentheses as a free bonus.

最后,我还建议更改 handle_error 的名称以更好地反映它的实际作用.(report_error,也许?)处理错误"通常意味着清理事情以解决错误,以便继续执行.如果你想让你的 handle_error 阻止调用它的代码继续,那么它似乎不太可能清理事情以使继续成为可能,并且再次,它会导致讨厌的,难以-使用此代码的未来程序员的调试惊喜.

Finally, I would also suggest changing the name of handle_error to better reflect what it actually does. (report_error, maybe?) "Handling an error" usually means cleaning things up to resolve the error so that execution to continue. If you want your handle_error to prevent the code which called it from continuing, then it seems very unlikely that it's cleaning things up to make continuation possible and, once again, it will cause nasty, hard-to-debug surprises for future programmers using this code.

这篇关于Perl 子程序是否可以强制其调用者返回?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆