如何在Perl中干净地处理错误检查?

时间:2009-08-03 16:44:39

标签: perl

我有一个Perl例程来管理错误检查。基于先前的成功,大约有10种不同的检查,有些是嵌套的。这些通常不是特殊情况,我需要croak / die。此外,一旦发生错误,执行其余检查就没有意义了。

但是,我似乎无法想出一个简洁的方法来解决这个问题,除非使用类似于以下可怕黑客的东西:

sub lots_of_checks
{

 if(failcond)
 {
  goto failstate:
 }
 elsif(failcond2)
 {
  goto failstate;
 }

 #This continues on and on until...

 return 1; #O happy day!

 failstate:

 return 0; #Dead...
}

我希望能做的事情是这样的:

do
{
 if(failcond)
 {
  last;
 }
 #...
};

6 个答案:

答案 0 :(得分:12)

空返回语句是从Perl子返回false而不是返回0的更好方法。后一个值在列表上下文中实际上是真的:

sub lots_of_checks {
    return if fail_condition_1;
    return if fail_condition_2;
    # ...
    return 1;
}

答案 1 :(得分:8)

也许您想查看以下有关perl5中异常处理的文章:

答案 2 :(得分:5)

你绝对可以做你喜欢的事。

Check: {
    last Check
        if failcond1;
    last Check
        if failcond2;
    success();
}

答案 3 :(得分:5)

为什么不使用例外?任何不应遵循代码正常流程的情况都是例外。使用“return”或“goto”实际上是相同的,只是“不是你想要的”。

(你真正想要的是延续,“return”,“goto”,“last”和“throw”都是特殊情况。虽然Perl没有完整的延续,但我们确实有逃避延续;请参阅{ {3}})

在您的代码示例中,您编写:

do
{
 if(failcond)
 {
  last;
 }
 #...
};

这可能与:

相同
eval {
   if(failcond){
       die 'failcond';
   }
}

如果你想变得棘手而忽略其他例外:

my $magic = [];
eval {
    if(failcond){
        die $magic;
    }
}
if ($@ != $magic) {
    die; # rethrow
}

或者,您可以使用上面提到的Continuation :: Escape模块。但 没有理由忽视异常;这是完全可以接受的 以这种方式使用它们。

答案 4 :(得分:4)

根据你的例子,我会这样写:

sub lots_of_checks {
    local $_ = shift;  # You can use 'my' here in 5.10+

    return if /condition1/;
    return if /condition2/;
    # etc.

    return 1;
}

请注意return而不是return 0。这通常更好,因为它尊重背景;标量上下文中的值为undef,列表上下文中的值为()(空列表)。

如果你想保持一个单一的退出点(稍微不是Perlish),你可以不用goto来做到这一点。作为last州的文档:

  

...一个块本身在语义上与执行一次的循环相同。   因此,“最后”可用于实现早期退出此类块。

sub lots_of_checks {
    local $_ = shift;
    my $all_clear;

    {
        last if /condition1/;
        last if /condition2/;
        # ...
        $all_clear = 1; # only set if all checks pass
    }

    return unless $all_clear;
    return 1;
}

答案 5 :(得分:2)

如果您想保留单个输入/单输出结构,可以稍微修改其他建议以获取:

sub lots_of_checks
{
    goto failstate if failcond1;

    goto failstate if failcond2;

    # This continues on and on until...

    return 1; # O happy day!

    failstate:

    # Any clean up code here.

    return; # Dead...
}

IMO,Perl使用语句修饰符形式“如果EXPR返回”使得保护条款比C语言更具可读性。当您第一次看到该行时,您知道您有一个保护条款。这个功能经常被诋毁,但在这种情况下我非常喜欢它。

goto与语句修饰符一起使用可保留清晰度,并减少混乱,同时保留单一退出代码样式。当我在例行程序验证失败后进行复杂的清理时,我已经使用过这种形式。