2017-08-24 39 views
2

目前还不清楚我为什么下面的一段代码给我的错误:即使我从Try :: Tiny的finally块中返回一个值,为什么我会得到'使用未初始化值'的警告?

Use of uninitialized value in addition (+) at combined_op_test.pl line 12.

我期待的$success_count值由在每次迭代子程序的返回值递增。

下面是代码:

#!/usr/bin/env perl 
use strict; 
use warnings; 

use 5.014; 
use Try::Tiny; 

my $success_count = 0; 

for (1..10) { 
    $success_count += error_causing_sub(); 
} 

sub error_causing_sub { 
    try { 
     die ("Error."); 
    } catch { 
    } finally { 
     if (@_) { 
      say "Error occured."; 
      return 0; 
     } 
     else { 
      say "Error did not occur."; 
      return 1; 
     } 
    }; 
} 

任何帮助表示赞赏。

回答

4

如在文档的CAVEATS部分解释的,return不从子返回,从finally返回:

return returns from the try block, not from the parent sub (note that this is also how eval works, but not how TryCatch works):

sub parent_sub { 
    try { 
    die; 
    } 
    catch { 
    return; 
    }; 
    say "this text WILL be displayed, even though an exception is thrown"; 
} 

由于@simbabque notesfinally返回值被忽略。如果try出现故障,catch返回值是相关的,它是空的:

The return value of the catch block is not ignored, so if testing the result of the expression for truth on success, be sure to return a false value from the catch block: ...

下面的代码看起来更合乎逻辑的对我说:

#!/usr/bin/env perl 
use strict; 
use warnings; 

use 5.014; 
use Try::Tiny; 

my $success_count = 0; 

for (1..10) { 
    $success_count += error_causing_sub(); 
} 

say $success_count; 

sub error_causing_sub { 
    my $ret; 
    try { 
     die ("Error.") if rand(1) < 0.5; 
     say "Error did not occur."; 
     $ret = 1; 
    } catch { 
     say "Error occured."; 
     $ret = 0; 
    }; 

    return $ret; 
} 

此外,据我所知,the issues with eval that made Try::Tiny relevant were fixed in 5.14。所以,使用它可能会更好:

#!/usr/bin/env perl 
use strict; 
use warnings; 

use 5.014; 

my $success_count = 0; 

$success_count += error_causing_sub() for 1 .. 10; 

say $success_count; 

sub error_causing_sub { 
    my $ret; 
    eval { 
     die ("Error.") if rand(1) < 0.5; 
     say "Error did not occur."; 
     $ret = 1; 
    } or do { 
     say "Error occured."; 
     $ret = 0; 
    }; 

    return $ret; 
} 
+1

这并不完全。 'finally'的RV被忽略。如果失败,catch的RV是相关的,并且是空的。没时间写我自己的答案。你可以通过改变'catch {1}'来看到 – simbabque

+1

5.14固定的if($ @)'。最后一个片段不使用'if($ @)',所以它在5.14之前就可以工作。 – ikegami

相关问题