2017-04-08 10 views
2

私は再開可能な例外で遊んでいます。この例では、数え切れないものを数えようとしています。私はそれをキャッチし、実行し、その後$value変数にappropirate値を与える再開しようとすると:このPerl 6 CATCHブロックは、語彙スコープ内の変数を変更できますか?

try { 
    my $m = 'Hello'; 
    my $value; 
    $value = +$m; 
    put "Outside value is 「{$value.^name}」"; 
    CATCH { 
     when X::Str::Numeric { 
      put "「$m」 isn't a number!"; 
      put "「$m」 isn't a number!"; 
      put "Inside value is 「{$value.^name}」"; 
      $value = 0; 
      put "Inside value is now 「$value.」"; 
      .resume; 
      } 
     default { 
      put "Unhandled type 「{.^name}」"; 
      } 
     } 
    put "End of the block"; 
    } 

put "Got to the end."; 

CATCHブロックは、それがであるレキシカルスコープを見ることができ、それが中断したところから再開をピックアップします。私は$valueを変更し、ブロックの残りの部分はその値を使用し持つことができるだろうと期待されるが、CATCHの外の値は失敗になり:

「Hello」 isn't a number! 
Inside value is 「Any」 
Inside value is now 「0.」 
Outside value is 「Failure」 
End of the block 
Got to the end. 

アップは何?

+1

私はそれが評価効果の順序であると思われます:例外は '$ value = + $ m'ステートメントを中断しているようで、' CATCH'ブロックが実行された後に割り当てが行われ、0を上書きします。 – Christoph

答えて

4

ブロック内で、use fatalが有効になり、メソッドまたはサブ呼び出しから返された遅延例外がすぐにスローされます。 tryブロックのレキシカルスコープ外では、次の点に注意してください

my $value = +$m; 

$valueに割り当てられているFailureことになります。

my $value = force-failure(+$m); 
あなたが何かのように定義されている想像できる

sub force-failure(Mu \f) { f.sink if f ~~ Failure; f } 

コンパイラはこれを実行するためのコードを吐き出すので、(私は手を振ってるtryは、より多くのようなものに変換しますインラインで、いくつかの最適化で)。

考慮中のケースでは、.sinkがスローされた例外をトリガします。 CATCHブロックが実行されます。 .resumeは、普通はCATCHブロックで起こるように呼び出しスタックを巻き戻したくないことを示しているので、実行はforce-failureの内部で続き、f - Failureを返します。これはすべて、メインラインコードの割当前に$valueに行われます。したがって、ブロックCATCHによって指定された値を上書きして、Failureが割り当てられます。

残念ながら、でこれをエスケープすることはできません。これは、RHSを実行する前にテストが行​​われるためです(私たちが通常はやりたいことです)。

:しかし、行うことが可能です:通常のイディオムは全く tryブロックを持っていないことであろう、ととしてそれを書くことがあるため

もちろん
my $numified = +$m; 
my $value //= $numified; 

、これは、不自然な例のすべてのビットです

my $value = +$m // 0; 

したがって、Failureを利用してください。一般に、再開可能な例外は、多くの場合、再開が発生することを期待して書かれないため、十分な注意を必要とします。 Failureを致命的にするために生成されたコードはそのようなものの1つです。

+0

文書化された?私はあいまいな参照を見つけるだけです。 –

+1

うまくいけば、誰かが不足しているか不明確な文書を見つけたら、その人はhttps:// githubで問題を作成します。com/perl6/docであるので、少なくともその問題は見られ、亀裂にならないでしょう。 –

+1

これまでのところ、私は医者の問題については恥ずかしがり屋ではなかったが、私は先に宿題をしたい。だから、https://github.com/perl6/doc/issues/1274とhttps://github.com/perl6/doc/issues/1275があります。 –

関連する問題