Smart::Args::TypeTinyには, default
と optional
というパラメータがあります.
default
default
は, 引数が渡らなかった時のデフォルト値を指定するパラメータです.
use strict; use warnings; use feature qw(say); use Smart::Args::TypeTiny qw(args); sub test { args my $arg => { isa => 'Str', default => 'bar' }; return $arg // 'undef'; } say test(arg => 'foo'); # => 'foo' say test(); # => 'bar' ( default が使われる ) say test(arg => undef); # => Type check failed in binding to parameter '$arg'; Undef did not pass type constraint "Str" (エラー)
なお, isa
が Maybe
の場合はこうなります:
use strict; use warnings; use feature qw(say); use Smart::Args::TypeTiny qw(args); sub test { args my $arg => { isa => 'Maybe[Str]', default => 'bar' }; return $arg // 'undef'; } say test(arg => 'foo'); # => 'foo' say test(); # => 'bar' say test(arg => undef); # => 'undef'
まとめると, default
のパラメータがあるときは,
- 引数として
undef
以外を渡す ... 渡した値が使われる (isa
を満たさない場合は当然エラーになる) - 引数を渡さない ...
default
が使われる - 引数として
undef
を渡すisa
がMaybe
である ...undef
がそのまま使われる (default
は使われない)isa
がMaybe
でない ...isa
を満たさないのでエラーになる
...という挙動になります.
optional
一方, optional
はその名の通り, オプショナルであることを指定するパラメータです.
use strict; use warnings; use feature qw(say); use Smart::Args::TypeTiny qw(args); sub test { args my $arg => { isa => 'Str', optional => 1 }; return $arg // 'undef'; } say test(arg => 'foo'); # => 'foo' say test(); # => 'undef' (`optional` なので引数を渡さなくても問題ない. その場合は undef となる) say test(arg => undef); # => 'undef' (明示的に引数として`undef`を渡しても問題ない)
まとめると, optional
のパラメータがあるときは,
- 引数として
undef
以外を渡す ... 渡した値が使われる (isa
を満たさない場合は当然エラーになる) - 引数を渡さない ... エラーにならず,
undef
として扱われる - 引数として
undef
を渡す ... (isa
を満たしていなくても)エラーにならず, そのままundef
として扱われる
default
とoptional
では, default
とoptional
のどちらも指定した場合はどうなるでしょうか.
use strict; use warnings; use feature qw(say); use Smart::Args::TypeTiny qw(args); sub test { args my $arg => { isa => 'Str', optional => 1, default => 'bar' }; return $arg // 'undef'; } say test(arg => 'foo'); # => 'foo' say test(); # => 'bar' (`optional` なので引数を渡さなくても問題ない. その場合は `default` で指定された値となる) say test(arg => undef); # => 'undef' (明示的に `undef` を渡しても問題ない)
この挙動, よくよく見ると2番目に紹介したdefault
を指定 + isa
がMaybe
と同じですね. つまり1つの挙動(optionalな引数で, undef
を受け取れて, デフォルト値を指定したい)について, 2通りの書き方がある, ということです.
papixの意見
...とはいえ同じ挙動を複数の書き方ができる, というのは混乱を呼びそうです. どちらかに寄せよう! という合意を取れるといいのかな, と思います.
自分なら, こういう場合は前者(default
を指定 + isa
をMaybe
にする)として, default
とoptional
は同時に使わない... というふうにするのがわかりやすいんじゃないかな, と思いました.
というわけで以上です, すいませんがオチはないです...