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

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 ...

多分週刊チラシの裏 (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 上の対話で当事者双方が納得し合っ...

多分週刊チラシの裏 (Oct 19, 2020 - Feb 26, 2021)

週刊とは言ったが毎週刊とは言ってないという言い訳。 C++ のコンパイルを高速化する小技 ビルドシステムやツールを変更せずともコーディングだけで改善できるコンパイル時間短縮テクニック。 #include を減らす インライン化を明示的に避ける 関数オーバーロードの可視性を制限する 公開シンボルを減らす の 4 本。 歯医者で歯を治したら記憶能力を失った話 歯医者で簡単な治療を受けた日から後、記憶が 90 分しか保持できなくなった英国の軍人の話。まるで「博士の愛した数式」だが実話である。 DRPK で売られていた Sim City っぽいゲームのリバースエンジニアリング 平壌市内のアプリストア (物理) で売られていた Sim City 風ゲームがインストールに失敗してライセンス認証で止まってしまったのでなんとか動かせないものかとリバースエンジニアリングしてみた話。 日本にあっては DPRK のデジタル事情というと 3G セルラーが現役とか国内 Web サイトのリストがポスター一枚に収まるとか何故かコンピュータ将棋の古豪とかの断片的な情報が伝え聞かれる程度だが、近頃は Android タブレットでゲームなどもできるらしい。 国内のインフラ及びエコシステム事情に合わせて元々フリーミアム + アプリ内課金モデルだったものが買い切り 5,000 KPW (< 1 USD) になっているなど、我々が失った自由が我々よりも不自由な (はずだと我々が信じている) 国に残存しているのは皮肉だろうか。 typosquatting は単なる typo じゃ済まない typo を狙って人気のあるドメインやソフトウェアに類似した名前をつける手法 (typosquatting) は人を辟易させるのみならずセキュリティの脅威である。 IQT が 2017 年から 2020 年にかけて Python ライブラリの中央リポジトリである PyPI において行った調査で、メジャーなライブラリに名前を似せたマルウェアが 40 個確認されたとのこと。 その内 16 個が単純なスペルミス狙い (e.g., “urlib3” vs. “urllib3”) で、26 個は正当なパッケージと混同するような名前 (e.g., “nmap-python” vs. “pytho...

Mac から iPhone のカメラを起動して写真を直接取り込める

Via: The Verge ID セルフィーや (物理) 書籍のページスキャンなど携帯電話のカメラを使って写真を取り込むことは日常的な所作になっているが、写真の使い途が何かの申し込み用 Web フォームなどで iPhone より Mac の方が操作し易いときなどは億劫だ。Mac 組込の FaceTime カメラは 720p とか 1080p しかなくて非力すぎ、かといって iPhone で一旦撮影したものを Photos から探して AirDrop するのも面倒である。 実は macOS Mojave / iOS 12 以降には Continuity Camera という機能がある。これを使うと Apple 製の Mac アプリケーションから iPhone / iPad のカメラを起動して、余計な中間コピーを残すことなく写真を Mac に転送できる。 使い方は簡単で、対応している Mac アプリケーションのコンテキストメニューに “Import (or Insert) from iPhone (or iPad)” という項目がある。“Take Photo” だと一枚、“Scan Documents” だと複数の写真を (歪み補正しつつ) 連続で撮影して転送できる。 対応 Mac アプリケーションは Finder のほか iWork (Keynote, Numbers, Pages), Mail, Messages, Notes, TextEdit となっている、のだが実は Preview でも使える。同様にコンテキストメニューあるいは “File” メニューから起動できる。

Perl 5 to 6 - コンテナと値

これはMoritz Lenz氏のWebサイト Perlgeek.de で公開されているブログ記事 "Perl 5 to 6" Lesson 10 - Containers and Values の日本語訳です。 原文は 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 10 - コンテナと値 SYNOPSIS my ($x, $y); $x := $y; $y = 4; say $x; # 4 if $x =:= $y { say '$x and $y are different names for the same thing' } DESCRIPTION Perl6はコンテナと、コンテナに格納できる値を区別して取り扱います。 通常のスカラ変数は一種のコンテナで、型制約やアクセス制約(読み取り専用とか)などの属性を持ち、他のコンテナの別名として使えます。 値をコンテナに格納することを代入と呼び、コンテナに別名をつけることをバインディングと呼びます。 my @a = 1, 2, 3; my Int $x = 4; @a[0] := $x; # @a[0]と$xは同じ変数 @a[0] = 'Foo'; # エラー 「型チェック失敗」 Int や Str のような型は不変、つまりこれらの型のオブジェクトは変更できません。しかしこれらの値を保持する変数(コンテナ)は変更できます: my $a = 1; $a = 2; # 驚くにはあたりません バインディングは ::= 演算子を使ってコンパイル時に行うこともできます。 2つの変数がバインディングされているか調べるに...