2017-08-24 11 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 notes

として、finallyの戻り値は無視されます。 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

関連する問題