🙅

Falsy について

2020/10/01に公開

Falsy

  • 偽とみなされる値のこと。
  • プログラミング言語ではいわゆる boolean 型の false 以外の値でも、真偽判定の時に false 相当(=偽)と判定される値があることがある。
  • いわゆる boolean 型への暗黙の型変換の一種と考えてよい。
    • 本当のところプログラミング言語によりどう処理されているかは言語仕様を見ないとはっきりしない。
  • これはコードを書きやすくするための糖衣構文の一種になっている。
    • プログラミング言語の設計思想によるため、善し悪しは明確ではない。
  • Falsy の反対は Truthy
  • Falsy でもなければ Truthy でもないという値は通常存在しない。(排中律)
    • SQL では TRUE, FALSE, NULL(unknown) の3値論理になっているので要注意。
  • Falsy, Truthy の概念は、バグの要因になりやすい。
    • Falsy と Truthy の範囲が誤解されているため、バグの要因になりやすい。
      • 例えば、0 が Falsy、0 以外が Truthy であるにも関わらず、1 が Truthy と誤認しているコードが後を絶たない。
        • C言語/C++では、真偽値を0と1に変換する仕様になっていて、真偽判定の時には、0か非0かを判定している。このため、1で判定しても大丈夫なことがあり、話がややこしくなっている。
      • 例えば、空文字列または"0"が Falsy であるにも関わらず、空文字列のみが Falsy と誤認しているコードが後を絶たない。
      • 例えば、Map.get のようなもので値を取得した時に、存在しないことを示す値(例えば undefined)と、読み出した値そのもの(例えば null)が両方 Falsy であることがある。
    • プログラミング言語により異なっているため、バグの要因になりやすい。
      • 例えば、JavaScript, Python では "0" は Truthy、PHP, Perl では "0" は Falsy
      • 何も考えずにコードを見たまま移植するとバグとなる。
      • 別の言語を習熟済みのプログラマがうっかり書き間違える事故が多発する。
  • このため、明示的な型変換を要求するのが最近の主流になりつつある。

Falsy の概念を持たない代表的な言語

  • C#
  • D
  • Java
  • Rust

Falsy の概念がある代表的な言語

  • false 以外に false として扱われる値があるならば、ここに入れる。

C言語/C++

意味
0 数値の0
NULL, ((void*)0) NULLポインタ
false false (C99~)
  • NULL ポインタの内部表現は 0 の内部表現と等しいわけではない。0 と比較するべきではない。

JavaScript

意味
false false プリミティブ値
0 数値の0
-0 数値のマイナス0
"" 空文字列(長さ0の文字列)
null null ポインタ
undefined undefined プリミティブ値
NaN 非数

PHP

意味
FALSE FALSE プリミティブ値
0 数値の0
"" 空文字列(長さ0の文字列)
"0" 文字列での"0" (1文字の"0"の時のみ偽)
array(), [] 長さ0の配列
null null プリミティブ値

Ruby

  • Ruby にはいわゆる boolean 型はなく、TrueClass と FalseClass がある。評価すると TrueClass は真を返し、FalseClass は偽を返す。
  • NilClass も偽を返す。
  • FalseClass と NilClass 以外のオブジェクトは評価するとすべて真を返す。
意味
false false (FalseClass のインスタンス)
nil nil (NilClass のインスタンス) (非存在を示す値)

Python

意味
False False プリミティブ値
None None プリミティブ値 (非存在を示すポインタの一種)
0, 0.0, 0j, Decimal(0), Fraction(0, 1) 数値の0 (0と等しい値すべて)
'', (), [], {}, set(), range(0) 空のシーケンスまたはコレクション

Perl

意味
0 数値の0 (0と等しい値すべて)
"" 空文字列(長さ0の文字列)
"0" 文字列での"0" (1文字の"0"の時のみ偽)
長さ0のリスト
要素数0のハッシュ
undef 未定義値
未定義変数
  • 文字列に変換したときに''(空文字列)または'0'(文字列で数字1文字のゼロ)に変換されるなら偽、というのが直感的な理解とのこと。

参考

Discussion