1
2

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で関数の引数チェック

Posted at

今回は、Smart::Args をより活用する方法をご紹介します。

基本的な使い方

基本的な使い方の詳細は、前回の記事をご覧ください。

args or args_pos で引数の型を指定すると、型チェックしてくれるモジュールです。

use strict;
use warnings;
use utf8;
use Smart::Args;
# args: 名前付きでの指定
hoge(msg => "hello");
sub hoge {
    args my $msg => 'Str';
    print $msg;
}
# args_pos: 指定順での指定 
fuga(2);
sub fuga {
    args_pos my $arg => 'Int';
    print $arg;
}

今回は、さらに様々なパターンの活用方法を記載します。

型の種類

様々な種類の型を指定することができます。

型名 説明
Any
 Item
  Bool 0 or 1 or "" or undef
  Maybe['a] undef or 型名
  Undef undef (not Defined)
  Defined defined
   Value
    Str 文字(数字も含む)
     Num 小数も含む数値
      Int 整数のみ
     ClassName ex: Hoge::Fuga
     RoleName ex: Hoge::Fuga::Role
   Ref
    ScalarRef ex: $scalar = \(my $var);
    ArrayRef['a] ex: $array = [ 1, 2 ];
    CodeRef ex: $code = sub{};
    RegexpRef ex: $regex = qr/^hoge$/;
    GlobRef ex: my $GLOB = *GLOB_REF;[[br]]  my $GLOB_REF = \$GLOB;
     FileHandle ex: open(my $fh, '<', "hoge.txt")
    Object ex: bless {}, 'Hoge';

'aには型名が入る
引用: https://metacpan.org/pod/Mouse::Util::TypeConstraints#Default-Type-Constraints

指定方法

2つの方法があります。(args, args_pos共通)

  • 直接指定する
sub hoge {
    args_pos my $msg => 'Str';
    print $msg;
}
  • isaを使って指定する
sub hoge {
    args_pos my $msg => {isa => 'Str'};
    print $msg;
}

isaは、主に他のオプションと一緒に利用したいときに使います。
また 複数の引数を指定するときは、,でつなげるだけでOKです。(isaも同様)

sub hoge {
    args_pos my $msg => 'Str', my $name => 'Str';
    printf "%s (%s)", $msg, $name;
}

型をチェックしないものは、なにも指定しない。

sub hoge {
    args_pos my $self, my $msg => 'Str';
    printf "%s (%s)", $msg, $name;
}

型の中身もチェックする

先ほど出てきた 'a の紹介です。
'aには、Strなどの型を定義します。
下記の例で、配列内に数字が以外が入っていた場合にエラーとしたいとき

use strict;
use warnings;
use utf8;
use Smart::Args;
my $array = [1, ""];
hoge($array);
sub hoge {
    args_pos my $arg => 'ArrayRef'; # ArrayRef なので OK
    print join " ", @$arg;
}
実行結果
1 に

上記の場合は、問題なく実行される。
ArrayRefの中身を指定してあげると・・・

use strict;
use warnings;
use utf8;
use Smart::Args;
my $array = [1, ""];
hoge($array);
sub hoge {
    args_pos my $arg => 'ArrayRef[Int]'; # ArrayRef内に数字(Int)以外が含まれていたので NG
    print join " ", @$arg;
}
実行結果
'$arg': Validation failed for 'ArrayRef[Int]' with value ARRAY(0x90a9dc) at C:/strawberry/perl/site/lib/Smart/Args.pm line 179.
        Smart::Args::_validate_by_rule(ARRAY(0x90a9dc), 1, "\$arg", "ArrayRef[Int]") called at C:/strawberry/perl/site/lib/Smart/Args.pm line 129
        Smart::Args::args_pos(undef, "ArrayRef[Int]") called at hoge.pl line 11
        main::hoge(ARRAY(0x90a9dc)) called at hoge.pl line 8

と表示されエラーとなる。

値を指定したときだけチェックする

optionalMaybe[]を使うと、引数が指定されたときにチェックできます。

use strict;
use warnings;
use utf8;
use Smart::Args;
hoge(1);    # OK
hoge(2, 2); # OK
hoge(3, "さん"); # NG
sub hoge {
    args_pos my $no => 'Int', my $mode => {isa => 'Int', optional => 1};
    if (defined $mode) {
        printf "%d (mode: %d)\n", $no, $mode;
    } else {
        printf "%d\n", $no;
    }
}
実行結果
1
2 (mode: 2)
'$mode': Validation failed for 'Int' with value さん at C:/strawberry/perl/site/lib/Smart/Args.pm line 179.
        Smart::Args::_validate_by_rule("\x{3055}\x{3093}", 1, "\$mode", HASH(0x69a9ec)) called at C:/strawberry/perl/site/lib/Smart/Args.pm line 129   
        Smart::Args::args_pos(3, "Int", undef, HASH(0x69a9ec)) called at hoge.pl line 13
        main::hoge(3, "\x{3055}\x{3093}") called at hoge.pl line 10

undefはOKとするとき(4)

use strict;
use warnings;
use utf8;
use Smart::Args;
fuga(4, undef);  # OK
fuga(5, 5);      # OK
fuga(6, "ろく"); # NG
sub fuga {
    args_pos my $no => 'Int', my $mode => 'Maybe[Int]';
    if (defined $mode) {
        printf "%d (mode: %d)\n", $no, $mode;
    } else {
        printf "%d\n", $no;
    }
}
実行結果
4
5 (mode: 5)
'$mode': Validation failed for 'Maybe[Int]' with value ろく at C:/strawberry/perl/site/lib/Smart/Args.pm line 179.
        Smart::Args::_validate_by_rule("\x{308d}\x{304f}", 1, "\$mode", "Maybe[Int]") called at C:/strawberry/perl/site/lib/Smart/Args.pm line 129     
        Smart::Args::args_pos(6, "Int", undef, "Maybe[Int]") called at hoge.pl line 13
        main::fuga(6, "\x{308d}\x{304f}") called at hoge.pl line 10

第2引数に文字列を指定していることでエラーがでている。

デフォルト値を設定する

defaultを使用すると、指定されていないときの初期値を設定できます。

use strict;
use warnings;
use utf8;
use Smart::Args;
hoge(1); # no のみ指定する
sub hoge {
    args_pos my $no => 'Int', my $num => {isa => "Int", default => 2};
    printf "no: %d, num: %d\n", $no, $num;
}
実行結果
no: 1, num: 2

no のみしか値を指定していないが、numにも値(指定したデフォルト値)が入っている。

まとめ

Smart::Argsをより活用することによって、
引数チェックするコードを書かなくてもチェックできるようになり
きれいにコードが仕上がります。

Perlは型が緩い部分もあるので、Smart::Argsを活用して型チェックしていきましょう。

1
2
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
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?