unless a xor b # 擬似コードつまり「排他的論理和の否定」という条件が普通に必要になりました。
Rubyでは、シンプルに「^」(ハット)で書けるらしい。
a ^ b # aとbの排他的論理和 true ^ true #=> false true ^ false #=> true false ^ true #=> true false ^ false #=> false
演算子「^」は引数は真偽値か数値しか取らない。排他的論理和が必要な場合、引数がBooleanでない場合にはブール値に変換してやる必要がある。
これをしないと、型によっては想定外の結果が返ってくる。
7 ^ 4 #=> 3 [1,2] ^ [3,4] #=> NoMethodError: undefined method `^' for [1, 2]:Array^というメソッドを持っていない型はエラーが出るし、数値だとビット演算の結果が返ってくるので、7(10) ^ 4(10) = 111(2) ^ 100(2) => 011(2) => 3(10)となるわけ。
7はtruthy、4はtruthyだから、truthy^truthy=falsy、と思っていると、戻り値が3(truthy)。
そこで、ブール値への変換ですが、例えば「!!」を使う。
!!a ^ !!b #=> aの真偽値とbの真偽値の排他的論理和 !!7 ^ !!4 #=> false !![] ^ nil #=> trueString(!!"hoge")だと確かに変換はされましたが、
warning: string literal in conditionwarningが出ました。ユーザ定義クラスとか配列だと特に問題なかった。
Railsだったらpresent?を使うと便利かも。
a.present? ^ b.present?ただ、present?は、{}(Hash)、[](Array)、""(String)はfalseを返すのでご注意。
"".present? #=> true !!"" #=> falseその方が都合がいいケースはもちろんあるでしょう。
.nil?
返信削除でよさそう?
a.nil? ^ b.nil?
削除a,bがBooleanだとうまくいかない。
冗長だが、
(a ? true : false) ^ (b ? true :false)
ならOK?