1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Perl Smart::Argsで引数チェック

Last updated at Posted at 2019-03-25

Perl 引数チェック

こんにちは!
皆さんPerl書いてますか?

今日は関数の引数のチェックについてのお話をしていきます。

とはいえ便利なモジュールがあるのでそのご紹介です。

Smart::Args

今回はこのモジュールを使って値をチェックしていきたいと思います。

インストール

いつものcpanmを実行してpackageを入れて使えるようにしましょう。

$ cpanm -v Smart::Args

最初はいろいろ入るので長いですが気長に待ちましょう。。。

使い方

使い方は簡単。

主に下記の2つを使用します。

  • args

    • 名前つきの引数をチェックしたいとき
  • args_pos

    • 名前つきではないとき

パッと説明してもわからないと思いますので、実際のコードを見ていきたいと思います。

args

名前つきの引数をチェックする

使い方は簡単で、引数を受け取るところにargsを付けるだけ。
受け取る側の変数名 が 引数のキー として利用できます。

use Smart::Args;

&hoge{piyo => 1};

sub hoge {
    args my $piyo;
    print $piyo;
}

引数が複数あるときは、並べて書いていく。

use Smart::Args;

&hoge(piyo => 1, fuga => 2); # OK

sub hoge {
    args my $piyo, my $fuga;

    printf "piyo: %d, fuga: %d\n", $piyo, $fuga;
}

piyofugaが渡されているかチェックできます。
問題なければ正常終了します。

結果出力
piyo: 1, fuga: 2

引数が足りないとき

use Smart::Args;

&hoge(piyo => 1); # 引数が足りない(fuga)

sub hoge {
    args my $piyo, my $fuga;

    printf "piyo : %d, fuga; %d\n", $piyo, $fuga;
}
実行結果
missing mandatory parameter named '$fuga' at sample.pl line 6.
        main::hoge("piyo", 1) called at sample.pl line 3

エラーがでてますね。

ちなみに 引数が多いとき は正常終了します。

sample.pl
use Smart::Args;

&hoge(piyo => 1, fuga => 2, foo => 3); # 引数が多い(foo)

sub hoge {
    args my $piyo, my $fuga;

    printf "piyo: %d, fuga: %d\n", $piyo, $fuga;
}
実行結果
piyo: 1, fuga: 2

型のチェック

sample.pl
use Smart::Args;

&hoge(piyo => 1, fuga => "fuga"); # 文字を渡している(fuga)

sub hoge {
    args my $piyo, my $fuga => 'Int';

    printf "piyo: %d, fuga: %d\n", $piyo, $fuga;
}
実行結果
'fuga': Validation failed for 'Int' with value fuga at C:/Strawberry/perl/site/lib/Smart/Args.pm line 179.
        Smart::Args::_validate_by_rule("fuga", 1, "fuga", "Int", SCALAR(0x29fd990)) called at C:/Strawberry/perl/site/lib/Smart/Args.pm line 63
        Smart::Args::args(1, undef, "Int") called at sample.pl line 6
        main::hoge("piyo", 1, "fuga", "fuga") called at sample.pl line 3

どのような型がチェックできるかというと・・・

Any
 Item
     Bool
     Maybe[`a]
     Undef
     Defined
         Value
             Str
                 Num
                     Int
                 ClassName
                 RoleName
         Ref
             ScalarRef
             ArrayRef[`a]
             HashRef[`a]
             CodeRef
             RegexpRef
             GlobRef
                 FileHandle
             Object

いろいろありますね!

さきほどまでの例だと第2引数しか型チェックできていません。
すべての引数をチェックしたいときは、それぞれに型の指定が必要です。

args my $hoge => 'Int', my $fuga => 'Int';

任意なキー

渡すかどうかわからない引数ってありますよね。
そんなときに使えるoptionalというのが用意されています。

use Smart::Args;

&hoge(fuga => 1, piyo => 2); # ok
&hoge(fuga => 1); # ok

sub hoge {
    args my $fuga, my $piyo => {optional => 1};
    printf "ok\n";
}
結果出力
ok
ok

引数が渡されなかった変数(上の場合だと2回目の$piyo)、値はundefとなります。

初期値

指定されなかったら初期値入れておいてほしいというときもあると思います。
そんなときにはdefaultを使います。

use Smart::Args;

&hoge(fuga => 1, piyo => 3); # fuga: 1, piyo: 3
&hoge(fuga => 1); # fuga: 1, piyo: 2

sub hoge {
    args my $fuga, my $piyo => {default => 2};

    printf "fuga: %d, piyo: %d\n", $fuga, $piyo;
}
結果出力
fuga: 1, piyo: 3
fuga: 1, piyo: 2

defaultを使用した場合、常に値が入った状態になるので指定しなくても大丈夫になります。

型の指定

my $hoge => 'Int'というように型をチェックしていましたが、
他のオプションと一緒に値の型チェックもしたいというときは、isaを使います。

sample.pl
use Smart::Args;

&hoge(fuga => 1, piyo => "foo"); # piyoが文字になっている

sub hoge {
    args my $fuga, my $piyo => {isa => 'Int', default => 2};

    printf "piyo: %d, fuga: %d\n", $piyo, $fuga;
}
結果出力
'piyo': Validation failed for 'Int' with value foo at C:/Strawberry/perl/site/lib/Smart/Args.pm line 179.
        Smart::Args::_validate_by_rule("foo", 1, "piyo", HASH(0xf3bec0), SCALAR(0x2a7e9c0)) called at C:/Strawberry/perl/site/lib/Smart/Args.pm line 63
        Smart::Args::args(1, undef, HASH(0xf3bec0)) called at sample.pl line 6
        main::hoge("fuga", 1, "piyo", "foo") called at sample.pl line 3

ハッシュ


# HashRef
&ex_hash(hoge => {});

sub ex_hash {
    args my $hoge => {isa => 'HashRef'};
}

# ArrayRef
&ex_hash_array(piyo => []);

sub ex_hash_array {
    args my $piyo => {isa => 'ArrayRef'};
}

配列内の型をチェック

&hash_array(fuga => ['Hoge', 'Piyo']);

sub hash_array {
    args my $fuga => {isa => 'ArrayRef[Str]'};
}

package名をチェック

my $hoge = Hoge->new;
$hoge->piyo;

package Hoge;
sub piyo {
    args my $self => {isa => 'Hoge'};
}

値が undef or 型 なとき

my $value = "abc";
# my $value = undef;

&fuga(hoge => $value);

sub fuga {
    args my $hoge => {isa => 'Maybe[Str]'}; # Str or undef
}

args_pos

名前つきでない引数をチェックする

use Smart::Args;

&hoge(1, 2);

sub hoge {
    args_pos my $piyo, my $fuga;

    printf "piyo: %d, fuga: %d\n", $piyo, $fuga;
}
結果出力
piyo: 1, fuga: 2

先程のコードと変わったところはあまりないですねw

これも先程と同じような型チェックなどができます。
もちろんご紹介したoptionaldefalutisaも同じように使用できます。

型チェックでオブジェクトから呼ばれているかチェックするなら・・・

sample.pl
{
    package Hoge;
    use Smart::Args;
    use Object::Simple -base;

    sub piyo {
        args_pos my $self => 'Object', my $fuga => 'Str';
        printf "%s\n", $fuga;
    }
}

my $hoge = Hoge->new;
$hoge->piyo("fuga!"); # OK

Hoge::piyo("fuga!") # NG
結果出力
fuga!
'self': Validation failed for 'Object' with value fuga! at C:/Strawberry/perl/site/lib/Smart/Args.pm line 179.
        Smart::Args::_validate_by_rule("fuga!", 1, "self", "Object") called at C:/Strawberry/perl/site/lib/Smart/Args.pm line 107
        Smart::Args::args_pos("fuga!", "Object", undef, "Str") called at sample.pl line 7
        Hoge::piyo("fuga!") called at sample.pl line 15

とこんな感じでObjectと指定してあげれば、
オブジェクト経由で呼ばれているのをチェックできます。

まとめ

Smart::Argsを使って簡単&楽に引数チェックをいれていきましょう!

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?