20190227のPerlに関する記事は1件です。

Perlにおける真偽値の概念は複雑だ

@yukikimoto さんのツイートを発端に色々調べることになった件をまとめますが、このまとめ自体へ方々からツッコミが入ると思います。

編集リクエスト、コメント大歓迎。皆さんの知識を借りて有用な記事にしたいと思います。

Perlにおける真値とは?

代表的な値として1が挙げられますが、これは正確ではありません。Perlでは、偽値でないあらゆる値が真値です。偽値の定義が複雑なのでもはやこう表現するほかありません。

Perlにおける偽値とは?

他言語との比較でよくある誤解としてfalseという文字列があげられますが、これは真値です。falseという関数も(作らなければ)ありません。

とりあえず列挙。

  • 0'0'"0"
  • 空の文字列(''"")
  • 空のリストや配列'()' 
  • undef
  • 「真偽値コンテキストでの偽値」としか言い表せれない値1( !1など)

次に、一つ一つ見ていきましょう。

0'0'"0"

数学的に0と等価な値、および計算結果は数値型である限り偽です。2

例:0.00, 0x0,0e0, 3-2-1, sin(0)など
ただし、これらが文字列だった場合、'0'"0"を除いて真となります

空の文字列

length0になる文字列は偽です。'',""しかないはずです。

空のリスト

$#array名-1になるリストや配列は偽です。()しかないはずです。
機序について詳しい記事はこちら
なお、空のハッシュは空の配列と区別がつかない3ので省略します。

undef

undefは文字列コンテキスト、リストコンテキストで空になり、数値コンテキストで0になるので結果的に常に偽です。が、use warnings支配下では警告の原因になるので使わない方が良いかもしれないですね。

真偽値コンテキストでの偽値

例えば、!で反転した任意の真値は偽です。
他には比較演算子の結果が偽だった時の返値などが該当します。
私はこれがundefと等価だと勘違いをしていましたが、仕様上は別とのこと。4

どの辺がundefと違うの?

  • definedで真
  • なので、use warnings支配下で警告が出ない。

まとめ

Perlが直感的に正しいように設計されてるからこんなこと考えずに真偽判定できるけど、詳しく調べると深かった。積極的に区別して使いたいですね。

ひとことで言うと、文字列に変換したときに''か'0'にならなければ真です。

akajiroさんのツイートより
なるほどね。


  1. perldoc.jpの真偽値の項目参照 

  2. @xtetsuji さんのご指摘を受けて編集 

  3. 内部的に違うかもしれないが、Perlでの表現はともに()である 

  4. ルモーリンさんの検証ツイート 

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む