Ruby ||演算子の使い方

目次

概要

ある日、以下のようなコードを発見しました。

puts A.hoge || A.piyo || A.fuga

||ifとセットで(or文として)使われるものと思っていたため、||単体でどのような挙動をするのかわかりませんでした。😓

調査する中で知った仕様を、サンプルコードと合わせてまとめていきます!

検証環境

  • ruby 3.1.0p0 (2021-12-25 revision fb4df44d16) [arm64-darwin21]

検証

大まかな仕様

||は左から順に式を評価していきます。

式の結果がtrueの場合は処理が終わり、nilfalseの場合は次(右)の処理へと進みます。

そうです。場合によっては||に含まれる全ての式が評価されるわけではないのです。😳

IF文とセットの場合

まずは、IF文とセットの場合を検証します。

サンプルコード

def main
  puts 'main start'

  if method1 || method2 || method3 then
    puts 'this is true!!!'
  end

  puts 'main end'
end

def method1
  puts 'this is method1'
  false
end

def method2
  puts 'this is method2'
  true
end

def method3
  puts 'this is method3'
  true
end

main

実行結果

サンプルコードを実行すると以下のように出力されます。

main start
this is method1 # method1が実行され、falseが返る
this is method2 # method2が実行され、trueが返る
this is true!!!
main end

# 「this is method3」が出力されない => method3は実行されていない

結果から分かるように、method3が実行されていません。😳

このように、||が連続している場合は左から処理を評価し、trueとなった時点で評価を終了するのです。

||のみの場合

それでは、||のみの場合を見てみましょう。

name, email, age属性を持つUserクラスを用いて検証します。

サンプルコード

def main
  puts 'main start'

  # 全属性を持っている
  user1 = User.new
  user1.name = 'hoge'
  user1.email = 'hoge@example.com'
  user1.age = 21

  # email,ageを持っている
  user2 = User.new
  user2.email = 'piyo@example.com'
  user2.age = 22

  # ageのみ持っている
  user3 = User.new
  user3.age = 23

  # ||のみの式
  puts user1.name || user1.email || user1.age
  puts user2.name || user2.email || user2.age
  puts user3.name || user3.email || user3.age

  puts 'main end'
end

class User
  attr_accessor :name, :email, :age
end

main

実行結果

main start
hoge # user1の結果
piyo@example.com # user2の結果
23 # user3の結果
main end

結果を以下にまとめました。

  • user1の場合
    1. nameが値を持っていたため、hogeが出力された
    2. emailおよびageも値を持っていたが、評価されなかった
  • user2の場合
    1. nameが値を持っていなかったため、次のemailが評価された
    2. emailが値を持っていたため、piyo@example.comが出力された
    3. ageも値を持っていたが、評価されなかった
  • user3の場合
    1. nameが値を持っていなかったため、次のemailが評価された
    2. emailが値を持っていなかったため、次のageが評価された
    3. ageが値を持っていたため、23が出力された

左から順に式が評価され、true(値を持っている)時点で評価を終了していることが分かります。👀

おわり

||の隠された(知らなかっただけ)挙動を知るきっかけとなりました!

挙動を正しく理解し、きれいなコードを書けるよう日々精進します!💪