今回は、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
と表示されエラーとなる。
値を指定したときだけチェックする
optional
やMaybe[]
を使うと、引数が指定されたときにチェックできます。
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を活用して型チェックしていきましょう。