【一人 Ruby Advent Calendar 2017】Ruby における真と偽【6日目】

一人 Ruby Advent Calendar 2017 6日目の記事になります。

Ruby おける真と偽

Ruby では『false もしくは nil 』は偽、『それ以外以外の全てのオブジェクト』は真になります。
なので、0 という数値も Ruby では真となります。

result = if 0
    42
end

p result
# => 42

他の言語では 0 が偽として扱われることも多いので Ruby を使う場合は注意する必要があります。

Ruby でビット演算する場合の注意

さて、例えば C++ で『任意のビットが立っているかどうか』を判定する為に & 演算子を使うことがあります。

// n に対して 0b0001 ビットが立っているかどうか判定する
if( n & 0b0001 ){
    std::cout << "ok" << std::endl;
}

これは n & 0b0001 の結果が 0 であれば『n0b0001 ビットが立っていない』と判定できるためです。
これをそのまま Ruby で書くと以下のようになると思います。

if n & 0b0001
    "OK"
end

ですが、上記のコードでは正しく動作しません。
なぜなら『C++ では 0 が偽』として扱われますが、『Ruby では 0 が真』として扱われるためです。
つまり C++ では『0b0000 & 0b01010 を返すので偽』となりますが、 Ruby では『0b0000 & 0b01010 を返しても真』となってしまうからです。

def check n
    if n & 0b0001
        "OK"
    else
        "NG"
    end
end

p check 0b1111
# => "OK"
p check 0b1100
# => "NG"

これを正しく動作させるためにはビット演算だけではなくて『結果が 0 かどうか』も判定する必要があります。

def check n
    if n & 0b0001 != 0
        "OK"
    else
        "NG"
    end
end

p check 0b1111
# => "OK"
p check 0b1100
# => "NG"

ちなみにこれを回避するために Integer#anybits? みたいなメソッドを入れるかどうかみたいな議論がされていたりします。

まとめ

  • Ruby では falsenil が偽
  • Ruby では falsenil 以外が真
  • 0 も真として扱われる
  • 0 を偽と扱うようなコードを記述する場合は注意する必要がある


真理値以外を返す比較演算子もあるので注意しましょう。

参照