Idea of Data::Validator

Smart::Argsは無駄がなくて使いやすいのですが、欠点はXSモジュール(PadWalker)への依存があることと、Perlの作法を完全に無視していることです。
そこで、試みにData::Validatorというモジュールを書いてみました。

コンセプトは以下の通り:

  • 機能的にはSmart::Args + X
  • Pure Perlでも動く
  • Perlの作法に則る
  • 十分に速い

使い方は以下の通り

#!perl -w
use 5.010_00;
use strict;
use Data::Validator;

sub request {
    state $rule = Data::Validator->new(
        url        => { isa => 'Str', xor => [qw(schema host path_query)] },

        schema     => { isa => 'Str', default => 'http' },
        host       => { isa => 'Str', default => '127.0.0.1' },
        path_query => { isa => 'Str', default => '/' },

        method     => { isa => 'Str', default => 'GET' },
    )->with('Method');

    my($self, $args) = $rule->validate(@_);
    say $args->{uri};
    ...;
}

これはFurlのrequest()メソッドの引数の一部を仮に定義したものです。主な引数としては完全なurl、またはurlのパーツを渡し、完全なurlとそのパーツは相互に排他的(exclusive or/xor)となっています。
型指定についてはSmart::Argsと互換性があり、Mouseのtype constraint名か任意のtype constraintオブジェクトを渡せます。したがって、type constraintというフレームワークのうえで型制約/型変換が可能です。
また、validatorの生成とvalidationを分けているのもポイントで、validatorの生成を一度だけに抑えることで高速化を図っています。

速度は以下の通り:
benchmark/simple.pl

$ perl -Ilib benchmark/simple.pl
Params::Validate/0.95
Smart::Args/0.06
Data::Validator/0.01
without type constraints
                Rate  P::Validate      S::Args D::Validator
P::Validate  19166/s           --         -52%         -69%
S::Args      40193/s         110%           --         -35%
D::Validator 62171/s         224%          55%           --

業界標準ともいえるParams::Validateの3倍ということで、充分高速といえるでしょう。
それにしても、Params::ValidateはXSモジュールなのにSmart::ArgsやData::Validatorより遅いのですね。XSにすれば無条件に速くなるというのは誤りだということがよくわかります。