2019-02-19

Rubyの`&&`と`||`

&&

&& をよく使うのは、if 式などでの条件を書くときだろう。つまるところ真か偽の結果を得ることを期待していると思う。

cond1 = true
cond2 = false
cond3 = true

if cond1 && cond2
  # 実行されない
end

if cond1 && cond3
  # 実行される
end

ここで気をつけたいのは返り値は true または false の2択では無いということ。 https://docs.ruby-lang.org/ja/latest/doc/spec=2foperator.html#and には次のように書かれている。

左辺を評価し、結果が偽であった場合はその値(つまり nil か false) を返します。左辺の評価結果が真であった場合には 右辺を評価しその結果を返します。

つまり左辺が偽であればそれが返るので nil または false があり得るし、左辺が真の場合は nilfalseに加えて様々な真の値が返り得るということ。

pp false && true # => false
pp nil && true # => nil

pp true && true # => true
pp true && false # => false
pp true && nil # => nil
pp true && 'hello' # => "hello"
pp true && 100 # => 100
pp true && [] # => []

Rubyでは nilfalse は偽でそれ以外は真という性質があるので、条件式として書く場合に問題になることは少ないと思うがこの動作はちゃんと認識しておこう。

||

|| も似たような感じ。
https://docs.ruby-lang.org/ja/latest/doc/spec=2foperator.html#or に次のように書かれている。

左辺を評価し、結果が真であった場合にはその値を返します。 左辺の評価結果が偽であった場合には右辺を評価し その評価結果を返します。

pp true || false # => true
pp true || 'hello' # => true
pp 'hello' || true # => "hello"

pp false || true # => true
pp false || 'hello' # => "hello"
pp false || [] # => []
pp false || 100 # => 100

&& は || より評価の優先順位が高い

https://docs.ruby-lang.org/ja/latest/doc/spec=2foperator.html に書かれているように、優先順位としては && の方が || より高い。

つまり次のような式があった場合は..

a && b || c && d

次のように脳内変換しよう。

(a && b) || (c && d)

おまけ:and と or

and&& と、or|| とそれぞれ同じだが、優先順位が異なる。
この4つだと && > || > and, or という順序になる。

自分はあまり使わないが、この記事を書きながら調べていて以下の記事は参考になった。
https://techracho.bpsinc.jp/hachi8833/2018_07_12/59092

後置の ifunless を使って書くことが多いけど、andor をうまく使うとより読みやすくなる場面も多そうだな〜と思った。

# dataの取得に失敗したら例外を投げる
fetch_data or raise RuntimeError "failed to fetch data"

# 更新があるかどうかをチェックし、なければreturnで終了
updates = check_for_update or return