Blog::kobaken

prove t/foo/bar/baz.t

Syntax::Keyword::Assertをリリースしました

metacpan.org

assert { ... } と書けば、ブロックの評価値に応じてアサーションします。キーワードプラグインを利用することで本番環境などアサーションが不要な時にパフォーマンスを損ねることなく利用できることが特徴です。コンパイル型言語のアサーションと同様の使い勝手だと思います。

use Syntax::Keyword::Assert;

sub hello($name) {
    assert { defined $name };
    say "Hello, $name!";
}

hello("Alice"); # => Hello, Alice!
hello();        # => Dies when STRICT mode is enabled

キーワードプラグインとは?

キーワードプラグインとは、Perlのパーサーにフックして構文拡張する機能で、Perlの開発者のPaul Evans氏がフル活用しています。 氏は、Perl本体に手をいれることなく、キーワードプラグインを利用して試作品をまず作り、コミュニティからのフィードバックを経て、Perl本体に取り込む進め方をしています。最近の try/catch, defer, class といった文法拡張はその結実です。

キーワードプラグインの動作のイメージは、こんな感じです。

  • ① パーザーが指定キーワードを発見!今回ならassert
  • ② 指定キーワード周辺のOPツリー(抽象構文木のようなもの)に、好みのOPツリーを差し込む!以上です!

例えば、このSyntax::Keyword::Assertの場合、assert { defined $name } は、次のコードと等価になるようにOPツリーを組み立てています。

# STRICTが有効な場合
croak 'Assertion failed' unless do { defined $name }

# STRICTが無効な場合は何もしない。

より具体的なソースコードはこちら

面白いですね!

開発話

余談ですが、OPツリーの組み立ては慣れてなかったので、その段取りを備忘として書き留めます。

まず、こんなサイクルで進めました。

  • 最初にキーワードで置き換えたい内容を Pure Perl で書く
    • 今回なら croak ... unless BLOCK
  • このコードに、B::Concise, B::Terse, B::Debug などを通して、OPツリーを把握する
  • 試しに書いたOPツリーが、👆のOPツリーと一致するか確かめる
  • 加えて、B::Deparseをして、期待するコードになっているか確かめる
  • → 期待通りになるまで頑張る

また、次の資料を参考にしました。

  • キーワードプラグインを利用したモジュールのソースコード
    • 今回なら、KEYWORD BLOCKという文法なので、Syntax::Keyword::Defer とOPツリーの組み立て以外、基本同じでした。
  • perlapiも読みつつ、perl本体のop.c や opnames.h も読むとOPツリーの組み立てが理解しやすかったです
    • そもそも SV、OPといった用語がよくわからない場合は、tokuhiromさんのこちらの記事を読むとイメージがつかめると思います。 C による Perl 拡張入門(
  • Yet Another CPAN Grep で関連コードを探すことも何度もしました

以上です! Happy Hacking!