HHeLiBeXの日記 正道編

日々の記憶の記録とメモ‥

Perlでの比較演算子・等価演算子の罠

はじめに

約1年ぶりに仕事でPerlのプログラムを書いたのだけど、その際にどうしても原因が分からなくてしばらく悩んでいたのでメモ。

1年前の時は無意識でちゃんと書いていたんだけどなぁ。

環境

CentOS 7.9

$ perl -v

This is perl 5, version 16, subversion 3 (v5.16.3) built for x86_64-linux-thread-multi
(with 44 registered patches, see perl -V for more detail)

Windows 11(XAMPPの付属物)

PS C:\xampp\perl\bin> .\perl.exe -v

This is perl 5, version 32, subversion 1 (v5.32.1) built for MSWin32-x64-multi-thread

Perlの比較演算子

Perlには、以下の2通りの比較演算子が存在する。

  • 「eq」「ne」「ge」「le」「gt」「lt」
  • 「==」「!=」「>=」「<=」「>」「<」

先に結論

前者は「文字列的な比較」、後者は「数値的な比較」とのこと。

1年前にコーディングしていた時はこれらを知らず、なおかつif ($val eq '')という比較しか書いていなかったので、ほぼ意識しなかった。

今回ハマったパターン

普段はPerlを使わないので、「等価比較===」という形で反射的にコーディングしていた。

実際に書いてハマっていたのは、if ($val == '')というコード。$valに何が来ようとTRUEになるのでおかしいと悩んで過去のコードを引っ張り出したところ、もしかしてeqじゃないとダメ?っていうことに気づいた。

1年前は20年以上ぶりにPerlのプログラムを書いたので、いろいろとサンプルなどを見ながら書いていて間違えなかったのだと思われる。

ググってみたところ、少し角度は違うが、検証している人がいた。

Perlのfalsyな値の==とeqによる比較結果 - dorapon2000’s diary

自分でもちょっと検証

警告を出すようにしてプログラムを実行してみる。

use warnings;

$val = '';
if ($val == '') {
    print "1: TRUE\n";
} else {
    print "1: FALSE\n";
}
if ($val eq '') {
    print "2: TRUE\n";
} else {
    print "2: FALSE\n";
}

結果は以下の通り(結果は、CentOS 7、Windows 11ともに同様)。

$ perl test1.pl
Argument "" isn't numeric in numeric eq (==) at test1.pl line 4.
Argument "" isn't numeric in numeric eq (==) at test1.pl line 4.
1: TRUE
2: TRUE

確かに警告が出る。