为什么我收到 'use of uninitialized value' 警告,即使我 return 来自 Try::Tiny 的 finally 块的值?

Why do I get 'use of uninitialized value' warnings even though I return a value from Try::Tiny's finally block?

我不清楚为什么下面的代码会给我错误:

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;
        }
   };
}

感谢任何帮助。

如文档的 CAVEATS 部分所述,return 不是来自子 return,而是 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";
}

作为finally的return值被忽略。如果 try 失败,catch 的 return 值是相关的,它是空的:

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;
}