A note on smart match op: $var ~~ constant vs. $var1 ~~ $var2

先日『初めてのPerl 第5版』を少し読んだところ,スマートマッチ演算子についての解説があった。
perlsyn/Smart matching in detailをみると非常に複雑な印象を受けるが,実際にはそれほど複雑ではないようだ。むしろ,うまく使うと非常に便利である。

ただし,スマートマッチ演算子を使うときは,常に変数と定数を比較するようにしたほうがよい。

以下,使用例と問題例を示す。

#!perl -w
use strict;
use feature 'say';
my $foo;

# $foo eq "foo" と同じ
# ただし$fooがundefでも警告がでない
say $foo ~~ "foo";

# $foo =~ /foo/ と同じ
# ただし$fooがundefでも警告がでない
say $foo ~~ qr/foo/;

# 以下の挙動に注意!
$foo = '00';
my $bar = '0';
say $foo ~~ $bar; # $foo eq $bar: false
scalar($bar+0); # numify
say $foo ~~ $bar; # $foo == $bar: true
__END__ 

どの比較でも,$fooがundefの場合は静かに偽を返す。つまり, defined($foo) でチェックする必要がない。

ただし,最後の例を見てわかるように,オペランドの型(文字列/数値)によって挙動が変わることに注意したい。つまり,右辺も左辺もスカラー変数だと,どのような比較が行われるのかを予測するのが非常に難しくなる。したがって,スマートマッチ演算子では,常に変数と定数を比較するのがよい。