Smart::Matchで快適スマートマッチ
こんにちは。Perlで遊ぶと言うより、 未だ、Perlに遊ばれているtaiju (id:jdg) です。
YAPC::Asia TOKYO2011に参加したので、爪あとを残すべく、Perl Advent Calendar 2011に参加することにしました。
さて、Perl5.10から導入されたスマートマッチですが、これをより快適に使えるモジュールがないか、CPANで探してみたところ、Smart::Matchというモジュールが見つかりましたので、ご紹介したいと思います。
Smart::Matchはスマートマッチを快適に使うためのユーティリティをたくさん提供しているモジュールのようで、デフォルトで比較演算子でスマートマッチが採用される、switch文などで便利に使えそうなユーティリティがたくさん導入されています。
junctive
Perl6のJunctionのような動作をするユーティリティ群です。
any, all, none, oneが該当します。
use 5.010;
use strict;
use warnings;
Smart::Match qw/:junctive :number positive negative/;
# any
given (1) {
say 'matched!' when any(1,2,3);
}
# all
given (1) {
say 'matched!' when all(1, number, positive);
}
# none
given (1) {
say 'matched!' when none('a', 2, []);
}
# one
given (1) {
say 'matched!' when one(odd, even, negative);
}
Junctionのように、スマートマッチ演算子以外で使うことは想定されていないので、その点は注意です。
スマートマット演算子以外でも使いたい場合は、Perl6::Junctionが使えます。
definite
必ずマッチするか、必ずマッチしない比較関数を提供するユーティリティ群です。
always, neverが該当します。
use 5.010;
use strict;
use warnings;
Smart::Match qw/:definite/;
# always
given (1) {
say 'matched!' when always;
}
given (undef) {
say 'matched!' when always;
}
# never
given (1) {
say 'not matched!' when not never;
}
given (undef) {
say 'not matched!' when not never;
}
boolean
真偽値になるかどうかを判定する時に使えるユーティリティ群です。
true, falseが該当します。
use 5.010;
use strict;
use warnings;
Smart::Match qw/:boolean/;
# true
given (1) {
say 'matched!' when true;
}
given ('foo') {
say 'matched!' when true;
}
# false
given (0) {
say 'not matched!' when false;
}
given ('') {
say 'not matched!' when false;
}
numeric
数に関する判定に使えるユーティリティ群です。
number, integer, even, odd, more_than, less_than, at_least, at_mostが該当します。
use 5.010;
use strict;
use warnings;
Smart::Match qw/:numeric all/;
# number
given (1) {
say 'matched!' when number;
}
# integer
given (1) {
say 'matched!' when integer;
}
given (1.5) {
say 'not matched!' when not integer;
}
# even
given (2) {
say 'matched!' when even;
}
# odd
given (1) {
say 'matched!' when odd;
}
# more_than
given (1) {
say 'matched!' when more_than(0);
}
# less_than
given (-1) {
say 'matched!' when less_than(0);
}
# at_least
given (1) {
say 'matched!' when all(at_least(0), at_least(1));
}
# at_most
given (-1) {
say 'matched!' when all(at_least(0), at_least(-1));
}
compare
値の比較に使えるユーティリティ群です。
numwise, stringwise, hashwiseが該当します。
use 5.010;
use strict;
use warnings;
Smart::Match qw/:compare/;
# numwise
given (1) {
say 'matched!' when numwise(1);
}
# stringwise
given ('foo') {
say 'matched!' when stringwise('foo');
}
# hashwise
given ({ foo => 1, bar => 2}) {
say 'matched!' when hashwise({ foo => 1, bar => 2});
}
meta
Smart::Match自身を拡張するユーティリティ群です。
match, delegateが該当します。
use 5.010;
use strict;
use warnings;
use Smart::Match qw/:meta integer odd always/;
# match
use constant fizz => match { scalar integer and $_ % 3 == 0 };
use constant buzz => match { scalar integer and $_ % 5 == 0 };
use constant fizzbuzz => match { scalar integer and $_ % 15 == 0 };
sub say_fizzbuzz {
for (1..100) {
given ($_) {
say "fizzbuzz" when fizzbuzz;
say "fizz" when fizz;
say "buzz" when buzz;
say $_ when always;
}
}
}
say_fizzbuzz;
# delegate
use constant nabe => delegate { $_ =~ /3/ ? 3 : $_ } fizz;
sub say_nabeatsu {
for (1..40) {
given ($_) {
say "aho!" when nabe;
say $_ when always
}
}
}
say_nabeatsu;
string
文字列に関するユーティリティ群です。
string, string_lengthが該当します。
use 5.010;
use strict;
use warnings;
use Smart::Match qw/:string/;
# string
given ('foo') {
say 'matched!' when string;
}
# string_length
given ('foo') {
say 'matched!' when string_length(3);
}
refs
オブジェクトの比較に使えるユーティリティ群です。
object, instance_of, ref_typeが該当します。
use 5.010;
use strict;
use warnings;
use Smart::Match qw/:refs/;
# object
given (bless([], 'main')) {
say 'matched!' when object;
}
# instance_of
given (bless([], 'main')) {
say 'matched!' when instance_of('main');
}
# ref_type
given ([]) {
say 'matched!' when ref_type('ARRAY');
}
arrays
配列に関するユーティリティ群です。
array, array_length, tuple, head, sequence, contains, sortedが該当します。
use 5.010;
use strict;
use warnings;
use Smart::Match qw/:arrays positive negative/;
# array
given ([]) {
say 'matched!' when array;
}
# array_length
given ([1,2,3]) {
say 'matched!' when array_length(3);
}
# tuple
given ([1,-1,1]) {
say 'matched!' when tuple(positive, negative, positive);
}
# head
given ([1,2,3]) {
say 'matched!' when head(1,2);
}
# sequence
given ([1,2,-1]) {
say 'not matched!' when not sequence(positive);
}
# contains
given ([1,2,3]) {
say 'not matched!' when not contains(1,2,4);
}
# sorted
given ([1,3,2]) {
say 'matched!' when sorted([1,2,3]);
}
hashes
ハッシュに関するユーティリティ群です。
hash, hash_keys, hash_values, sub_hashが該当します。
use 5.010;
use strict;
use warnings;
use Smart::Match qw/:hashes contains/;
# hash
given ({}) {
say 'matched!' when hash;
}
# hash_keys
given ({ foo => 1, bar => 2 }) {
say 'matched!' when hash_keys(contains('foo'));
}
# hash_values
given ({ foo => 1, bar => 2 }) {
say 'matched!' when hash_values(contains(1));
}
# sub_hash
given ({ foo => 1, bar => 2 }) {
say 'matched!' when sub_hash({ foo => 1 });
}
direct
値の比較とポインタの比較の関数を持ったユーティリティ群です。
address, valueが該当します。
use 5.010;
use strict;
use warnings;
use Smart::Match qw/:direct/;
# address
my $sub = sub {};
given ($sub) {
say 'not matched!' when not address(sub {});
}
# value
given ([1,2,3]) {
say 'matched!' when value([1,2,3]);
}
given ({ foo => 1, bar => 2 }) {
say 'matched!' when value({ foo => 1, bar => 2 });
}
given (1) {
say 'matched!' when value(1);
}
given ($sub) {
say 'not matched!' when not value(sub {});
}
その他
他にも、positive, negative, rangeというユーティリティ関数があります。これらはグループにまとめられていません。作者のミスなのかもしれませんが。
まとめ
version1未満ですし、ちょっと不安定な部分もある感じですが、Perl5.10以降が使える案件で、switch文を簡潔に書きたい際に、一部利用するのはいいかなと思いました。
次は、sakurako_sさんです。