スキップしてメイン コンテンツに移動

Perl 5 to 6 - 例外と制御例外

これはMoritz Lenz氏のWebサイトPerlgeek.deで公開されているブログ記事"Perl 5 to 6" Lesson 26 - Exceptions and control exceptionsの日本語訳です。

原文はCreative Commons Attribution 3.0 Germanyに基づいて公開されています。

本エントリにはCreative Commons Attribution 3.0 Unportedを適用します。

Original text: Copyright© 2008-2010 Moritz Lenz

Japanese translation: Copyright© 2011 SATOH Koichi

NAME

"Perl 5 to 6" Lesson 26 - 例外と制御例外

SYNOPSIS

try {
    die "OH NOEZ";

    CATCH { 
        say "there was an error: $!";
    }
}

DESCRIPTION

例外はその名前に反してまったく例外的なものではありません。実際のところPerl6では通常の制御フローの一部です。

例外は潜在的なエラー(例えば0除算、存在しないメソッドの呼び出し、型チェック失敗)またはdieその他の関数の明示的な呼び出しによって生成されます。

例外が投げられるとプログラムは呼び出しフレームからCATCHブロックかtryブロックを探し、スタックを完全に巻き戻します(つまりそれまでに呼び出された全部のサブルーチンから無理矢理戻ってくるということです)。 もしCATCHtryも見つからなければプログラムは終了し、運が良ければ役に立つエラーメッセージが表示されます。 どちらか一方が見つかった場合はエラーメッセージは特殊変数$!に格納され、CATCHブロックが実行されます(tryブロックにCATCHブロックがない場合、ブロックはundefを返します)。

ここまでの説明ではまだ例外が例外的なものに思えるかも知れませんが、エラー処理は些末なアプリケーションでもなければ不可欠です。 ただそればかりでなく、通常のreturn文も例外を投げているのです!

これは制御例外と呼ばれ、CONTROLブロックで捕捉することができ、そうしない場合はサブルーチン宣言で暗黙的に捕捉されます。

次の例を考えてみて下さい:

use v6;
my $block = -> { return "block"; say "still here" };

sub s {
    $block.();
    return "sub";
}

say s();

return "block"が制御例外を投げ、現在のブロックから抜ける(したがってstill hereは表示されない)のみならず、サブルーチンからも抜けます。これはsub s...宣言で捕捉されます。 ペイロード——この例では文字列——は戻り値として渡され、最後の行のsayがこれを表示します。

$block.()try { ... }ブロックの中に入れたりCONTROL { ... }ブロックをサブルーチンの本体に置いたりすることで例外を捕捉できます。

他のプログラミング言語とは逆にCATCH/CONTROLブロックはエラーが捕捉されるスコープの(外ではなく)中にあり、字句的変数への完全なアクセスが与えられています。このことは役に立つエラーメッセージを作るのを容易にし、またエラーが処理される前にDESTROYブロックが実行されることを防ぎます。

投げられない例外

Perl6はマルチスレッドの、特に自動並列化の考えを取り入れています。 1スレッドの終了が全スレッドに影響することがないように、「ソフトな」例外が考案されました。

関数がfail($obj)を呼ぶと特別な未定義値を返します。これはペイロードに$obj(大抵の場合はエラーメッセージ)とバックトレース(ファイル名と行番号)を格納しています。 この特殊な未定義値を確認なしに処理しようとすると通常の例外が投げられます。

my @files = </etc/passwd /etc/shadow nonexisting>;
my @handles = hyper map { open($_) }, @files;

この例のhyper演算子はmapに可能な限り動作を並列化するよう伝えます。 nonexistingファイルのオープンに失敗した場合、通常のdie "No such file or directory"では他のファイルオープン処理も中断してしまいます。 しかし失敗したオープン処理は代わりにfail("No such file or directory")を呼ぶので、呼び出し元は@handlesの内容を確認することができ、完全なエラーメッセージにもアクセスできます。

ソフトな例外が気に入らない場合、プログラムの最初にuse fatal;と書くとfail()から生じる例外が即座に投げられるようになります。

MOTIVATION

良いプログラミング言語にはエラー状態を扱うための例外が必要です。 成功したかどうか戻り値をいつも確認することは厄介だし忘れがちです。

伝統的な例外は暗黙の並列化にとっては有害なことがあるので、両者の最上の部分を組み合わせる解法が必要でした: 一度にすべてを殺してしまわず、またどんな情報も取りこぼしてしまわない方法がです。

コメント

このブログの人気の投稿

Perl 5 to 6 - コンテキスト

2011-02-27: コメント欄で既に改訂された仕様の指摘がありました ので一部補足しました。 id:uasi に感謝します。 これはMoritz Lenz氏のWebサイト Perlgeek.de で公開されているブログ記事 "Perl 5 to 6" Lesson 06 - Contexts の日本語訳です。 原文は Creative Commons Attribution 3.0 Germany に基づいて公開されています。 本エントリには Creative Commons Attribution 3.0 Unported を適用します。 Original text: Copyright© 2008-2010 Moritz Lenz Japanese translation: Copyright© 2011 SATOH Koichi NAME "Perl 5 to 6" Lesson 06 - コンテキスト SYNOPSIS my @a = <a b c> my $x = @a; say $x[2]; # c say (~2).WHAT # Str() say +@a; # 3 if @a < 10 { say "short array"; } DESCRIPTION 次のように書いたとき、 $x = @a Perl5では $x は @a より少ない情報—— @a の要素数だけ——しか持ちません。 すべての情報を保存しておくためには明示的にリファレンスを取る必要があります: $x = \@a Perl6ではこれらは反対になります: デフォルトでは何も失うことなく、スカラ変数は配列を単に格納します。 これは一般要素コンテキスト(Perl5で scalar と呼ばれていたもの)及びより特化された数値、整数、文字列コンテキストの導入によって可能となりました。無効コンテキストとリストコンテキストは変更されていません。 特別な構文でコンテキストを強制できます。 構文 コンテキスト ~stuff 文字列 ?stuff 真理値 +stuff ...

Perl 5 to 6 - ツイジル

これはMoritz Lenz氏のWebサイト Perlgeek.de で公開されているブログ記事 "Perl 5 to 6" Lesson 15 - Twigils の日本語訳です。 原文は Creative Commons Attribution 3.0 Germany に基づいて公開されています。 本エントリには Creative Commons Attribution 3.0 Unported を適用します。 Original text: Copyright© 2008-2010 Moritz Lenz Japanese translation: Copyright© 2011 SATOH Koichi NAME "Perl 5 to 6" Lesson 15 - ツイジル SYNOPSIS class Foo { has $.bar; has $!baz; } my @stuff = sort { $^b[1] <=> $^a[1]}, [1, 2], [0, 3], [4, 8]; my $block = { say "This is the named 'foo' parameter: $:foo" }; $block(:foo<bar>); say "This is file $?FILE on line $?LINE" say "A CGI script" if %*ENV.exists('DOCUMENT_ROOT'); DESCRIPTION いくつかの変数にはツイジルという第2のシジルがあります。これは基本的にはその変数が「普通」ではないということです。違いはいくつかあり、例えばスコープの違いなどです。 オブジェクトのパブリックな属性とプライベートな属性がそれぞれ . と ! というツイジルを持つことは既に紹介しました; それらは通常の変数ではなく self に結びつけられています。 ツイジル ^ はPerl5で例外的に扱われていたケースを一般化します。次のように書けます # 注意: Perl5のコードです sort ...

多分週刊チラシの裏 (Sep 28 - Oct 04, 2020)

Chrome Web Store が有料 Chrome 拡張の取扱を終了 Chrome Web Store で提供されている有料 Chrome 拡張及びアプリ内課金 API の両方が 2021 年 1 月いっぱいで廃止される。 開発者はそれまでに代替となるサードパーティの課金 API に移行し、購入済ライセンスの移行手段も用意する必要がある。 この決定の発表時点で新規の有料ないしアプリ内課金のある Chrome 拡張の新規登録は終了している。実際のところ 2020 年 3 月時点で既に「一時的に」停止されており、その措置が恒久化されただけとの由。 シェルスクリプティングには長いオプションを使え 「短いオプション (e.g., -x ) はコマンドライン上での略記である。スクリプトにおいては自分や将来の同僚のためにも長いオプション (e.g., ---do-something ) を与える方が理解が容易だろう」という主張。 異論の余地なく正論である。 CobWeb - COBOL to WebAssembly Compiler COBOL から WebAssembly へのコンパイラ。いやマジで。 Cloudflare が何を思ったか同社のサーバレス環境である Workers に COBOL 対応を追加した際 の成果物である。 COBOL から C へのトランスレータである GNU COBOL と C コードをコンパイルして WebAssembly を出力する Emscripten から成っており、他の言語に比べて軽量なバイナリを生成するとのこと。 「ウチではそんな風にはやらないんだ (“We don’t do that here”)」 昨今ソフトウェア開発のコミュニティでも Code of Conduct を用意するところが増えてきたが、コミュニティの文化を明文化するのは難しい。 長大な「べからず集」は息苦しいし、肯定的なガイドラインは時に抽象的で実効的に使えない。問題となるようなふるまいの動機が善意であった場合は特にそうだ。 仮に優れたガイドラインがあっても、それに基いて人を実際に咎めるのは骨が折れることである。初中やればコミュニティ内でも疎まれる。 話の分かる相手ならそれでもまだ説得する意義もあるが、Web 上の対話で当事者双方が納得し合っ...

Perl 5 to 6 - Perl5の演算子に対する変更

これはMoritz Lenz氏のWebサイト Perlgeek.de で公開されているブログ記事 "Perl 5 to 6" Lesson 11 - Changes to Perl 5 Operators の日本語訳です。 原文は Creative Commons Attribution 3.0 Germany に基づいて公開されています。 本エントリには Creative Commons Attribution 3.0 Unported を適用します。 Original text: Copyright© 2008-2010 Moritz Lenz Japanese translation: Copyright© 2011 SATOH Koichi NAME "Perl 5 to 6" Lesson 11 - Perl5の演算子に対する変更 SYNOPSIS # ビット演算子 5 +| 3; # 7 6 +^ 3 # 6 5 +& 3; # 1 "b" ~| "d" # 'f' # 文字列連結 'a' ~ 'b' # 'ab' # ファイルテスト if '/etc/passwd' ~~ :e { say "exists" } # 繰り返し 'a' x 3 # 'aaa' 'a' xx 3 # 'a', 'a', 'a' # 3項演算子 $a == $b ?? 2 * $a !! $b - $a # 連結比較 if 0 <= $angle < 2 * pi { ... } DESCRIPTION 数値演算子( + , - , / , * , ** , % )はすべて元のままです。 | 、 ^ 、 & はジャンクションの生成に使われるので、ビット演算子は構文が変更されました。 それらはデータプレフィクスを伴い、例えば ...

Perl 5 to 6 - サブルーチンとシグネチャ

これはMoritz Lenz氏のWebサイト Perlgeek.de で公開されているブログ記事 "Perl 5 to 6" Lesson 04 - Subroutines and Signatures の日本語訳です。 原文は Creative Commons Attribution 3.0 Germany に基づいて公開されています。 本エントリには Creative Commons Attribution 3.0 Unported を適用します。 Original text: Copyright© 2008-2010 Moritz Lenz Japanese translation: Copyright© 2011 SATOH Koichi NAME "Perl 5 to 6" Lesson 04 - サブルーチンとシグネチャ SYNOPSIS # シグネチャなしのサブルーチン——Perl5風 sub print_arguments { say "Arguments:"; for @_ { say "\t$_"; } } # 固定引数の型指定付きシグネチャ sub distance(Int $x1, Int $y1, Int $x2, Int $y2) { return sqrt ($x2-$x1)**2 + ($y2-$y1)**2; } say distance(3, 5, 0, 1); # デフォルト引数 sub logarithm($num, $base = 2.7183) { return log($num) / log($base) } say logarithm(4); # 第2引数はデフォルトを利用 say logarithm(4, 2); # 明示的な第2引数 # 名前付き引数 sub doit(:$when, :$what) { say "doing $what at $when"; } doit(what => 'stuff', when => 'once'); # ...