更新日:
【Ruby】 論理演算子(!, &&, ||, not, and, or)をまるごと学ぼう!
論理演算子とは、「真」と「偽」の2つの値だけで行う計算(論理演算)を表す記号のことです。Rubyの論理演算子には、「!, &&, ||, not, and, or」が用意されています。
論理演算子を使用すると、複数の条件式を組み合わせて判定することができます。
例えば、次のコードの||
は左辺と右辺どちらかの結果が真ならば、式全体の結果が真となり、then以下に記述する処理を実行することができます。
1
2
3
4
5
6
color = 'red'
if color == 'red' || color == 'blue' then
puts '色は赤、もしくは青です。' # 真だった場合に実行される
end
# 実行結果 色は赤、もしくは青です。
左辺のcolor == 'red'
が真となり、色は赤、もしくは青です。
が出力されていますね。
この記事では、各論理演算子の特徴や挙動をコードベースで学ぶことができます。論理演算子は条件分岐でよく使われるので是非マスターしましょう。
論理演算子とは?
論理演算子を理解するには、真偽値について知る必要があります。
真偽値とは簡単に説明すると、「ある条件が正しい(真)か正しくない(偽)か表すための値のこと」です。Rubyでは偽になる値はnilとfalseだけで、それ以外の値はすべて真になります。
例えば、ifは条件式の結果が「真」の場合にthen以下の処理を実行しますが、この条件式に10
とnil
をそれぞれ指定した場合は、次のようになります。
1
2
3
4
if 10 then
puts "真です" # 条件式の結果は「真」なので実行される
end
# 実行結果: 真です
1
2
3
4
5
6
if nil then
puts "真です"
else
puts "偽です" # 条件式の結果は「偽」なのでこちらが実行される
end
# 実行結果: 偽です
上記のように真偽値を使えば、条件が正しいか正しくないか表せますね。
そして真偽値は、2つ以上の真偽値を計算することができます。
加算の1+2
の計算結果が3
であるように、真偽値も計算によって1つの結果(答え)を得ることができます。
このように2つ以上の真偽値を計算して1つの結果を得ることを「論理演算」と呼びます。
四則演算には加算・減算・徐算・乗算の種類がありますが、それぞれ表すのに+ - / *
の記号が使われています。論理演算にも主に論理否定(NOT)、論理和(OR)、論理積(AND)の種類があり、! && ||
などの記号で表せます。
このような論理演算を表す記号のことを「論理演算子」と呼びます。
論理演算子の種類
Rubyの論理演算子には、次の表のように「!, &&, ||, not, and, or」が用意されています。
論理演算子 | 例 | 意味 |
---|---|---|
! not |
!A | Aが真のとき偽、偽のとき真を返す |
|| or |
A || B | AもしくはBが真のとき真、どちらも偽のとき偽を返す |
&& and |
A && B | AかつBが真のとき真、それ以外は偽を返す |
A || B
のように<左辺> [論理演算子] <右辺>
の式は左から順番に評価されます。
そして、次の画像のように左辺(A)を評価した時点で式全体の結果が決まらない場合のみ右辺(B)を評価(短絡評価)します。
また、Rubyの論理演算の結果(答え)は最後に評価された値になります。(後述します。)
以上の特徴を踏まえて各論理演算子について詳しくみていきましょう。
論理和(OR)
論理和(OR)を表す論理演算子は、||
とor
です。
1
2
式 || 式 # A || B
式 or 式 # A or B
基本的には、||
の方を使います。左辺(A)が偽なら右辺(B)を評価しますが、左辺が真ならその時点で左辺の値を返します。
それではサンプルコードでこの挙動を確認しましょう。
論理和の挙動を確認しよう
Rubyで偽の値はnilとfalseだけなので、次のコードで真になる値は10
とtrue
です。
1
2
nil || false || 10 || true
#(偽)|| (偽) || (真) || (真)
||
は左辺から順番に式を評価して「真」の時点でその値を返すので上記のコードを実行すると、次のように10
を返します。
1
2
irb(main):001:0> nil || false || 10 || true
=> 10
真である10が評価された時点で「式全体の結果として10が返る」ので、右辺の真であるtrueは評価されずに終わります。
全ての式の結果が偽の場合は、次のコードのように最後に評価された偽の値を返します。
1
2
irb(main):014:0> nil || false
=> false
論理和の使い所1 (ifとの併用)
||
は、次のコードのようにifと複数の条件を組み合わせることができます。
1
2
3
4
5
6
7
color = 'blue'
if color == 'red' || color == 'blue' || color == 'green' then
puts '色は赤、青、緑のどれかです。'
end
# 実行結果 色は赤、青、緑のどれかです。
ifは条件式の結果が真の場合にthen以下の処理を実行するので、上記ではcolor == 'blue'
が真でtrueを返すので処理が実行されます。
次の表のように||
の成立するパターンは3つあります。
A || Bが成立するパターン | 式全体の結果 |
---|---|
A=true, B=true(両方がtrue) | true |
A=true, B=false(片方がtrue) | true |
A=false, B=true(片方がtrue) | true |
論理和の使い所2 (変数に代入)
||
は、次のように演算結果を変数(value)に代入して使用することができます。
1
2
value = nil || false || 10 || true
# (偽)|| (偽) || (真) || (真)
変数(value)には、次のように最初に評価された「真」の値(10)が代入されます。「真」がない場合は、最後に評価された偽の値が代入されます。
1
2
irb(main):002:0> value
=> 10
また||
を上手く使うことで、未定義などで起こるエラーを防ぐことができます。
例えば、次のコードのnumber
のように定義されていないローカル変数を呼び出した場合にはNameErrorが発生します。
1
2
irb(main):001:0> number
NameError (undefined local variable or method `number' for main:Object)
このようなエラーは、「変数(number)が未定義の場合にデフォルト値を設定する」ことで防ぐことができそうですね。
そこで次のように記述すると、変数が未定義の場合に0を代入することができます。
1
2
irb(main):002:0> number || (number = 0) # 優先度で括弧が必要
=> 0
||
は、左辺が偽(nil,false)か未定義だと右辺が評価されるので、上記のコードでは左辺のnumberが未定義で右辺のnumber = 0
が評価されてnumberに0が代入されます。
そして、上記のコードは次のように||=
を使って置き換えることができます。
1
2
irb(main):002:0> number ||= 0 #number || (number = 0)と同じ
=> 0
このように||
の挙動を利用すれば、変数が偽(nil, false)か未定義のときにデフォルト値を設定することができます。
「or」と「||」の違いとは?
or
は、||
と同じ働きをしますが優先順位が低いです。orの優先順位は、他の演算子と比べても低い位置にあるので、考慮しなければ結果に影響を与える可能性があります。
例えば||
の演算結果を変数に代入した場合は、次のコードのようになります。
1
2
3
4
irb(main):011:0> is_empty = false || true
=> true
irb(main):012:0> is_empty
=> true
||
は最初に評価された「真」の値が代入されるので、is_empty
にはtrueが代入されます。orもこの働きは一緒なので同じようにtrueが代入されると考えますよね。しかし、実際に代入されるのは次のコードのようにfalseです。
1
2
3
4
irb(main):009:0> is_empty = false or true
=> true
irb(main):010:0> is_empty
=> false # is_emptyには、falseが代入されている
最初の式の結果でtrueを返しているので、 is_emptyにはtrueが代入されているようにみえますが、or
よりも=
の優先度が高いのでfalseが代入されます。
このようにorは優先度が低く他の演算子の影響を受けてしまうので、基本的には||
を使用するようにしましょう。
論理積(AND)
論理積(AND)を表す論理演算子は、&&
とand
です。
1
2
式 && 式 # A && B
式 and 式 # A and B
基本的には、&&
の方を使います。 左辺(A)が偽ならその時点で左辺の値(nil か false)を返します。左辺が真なら右辺(B)を評価します。
それではサンプルコードでこの挙動を確認しましょう。
論理積の挙動を確認しよう
Rubyで偽の値はnilとfalseだけなので、次のコードで真になる値は10
とtrue
です。
1
2
10 && true && false && nil
#(真) && (真) && (偽) && (偽)
&&
は左辺から順番に式を評価して「真」なら右辺を評価し、「偽」ならその値を返すので、上記のコードを実行すると、次のようにfalse
を返します。
1
2
irb(main):001:0> 10 && true && false && nil
=> false
偽であるfalseが評価された時点で「式全体の結果としてfalseが返る」ので、右辺の偽であるnilは評価されずに終わります。
全ての式の結果が真の場合は、次のコードのように最後に評価された式の値を返します。
1
2
irb(main):001:0> 10 && 0 && '' && [] && {} && 100
=> 100
論理積の使い所とは?
&&
は、次のコードのようにifと複数の条件を組み合わせることができます。
1
2
3
4
5
6
7
number = 30
if number <= 100 && number >= 50 then
puts 'numberは50以上100以下です。'
end
# 実行結果 numberは50以上100以下です。
ifは条件式の結果が真の場合にthen以下の処理を実行するので、上記ではnumber <= 100
とnumber >= 50
のどちらも真でなければ実行されません。
次の表のように&&
の成立するパターンは1つだけです。
A && Bが成立するパターン | 式全体の結果 |
---|---|
A=true, B=true(両方がtrue) | true |
このように条件が成立するパターンが1つしかないので、パターンが3つある||
よりもコードが読みやすいですね。
「and」と「&&」の違いとは?
and
は、&&
と同じ働きをしますが優先順位が低いです。andの優先順位は、他の演算子と比べても低い位置にあるので、orと同様に考慮しなければ結果に影響を与える可能性があります。
例えば&&
の演算結果を変数に代入した場合は、次のコードのようになります。
1
2
3
4
irb(main):022:0> is_empty = true && false
=> false
irb(main):023:0> is_empty
=> false
&&
は最初に評価された「偽」の値が代入されるので、is_empty
にはfalseが代入されます。andもこの働きは一緒なので同じようにfalseが代入されると考えますよね。しかし、実際に代入されるのは次のコードのようにtrueです。
1
2
3
4
irb(main):024:0> is_empty = true and false
=> false
irb(main):025:0> is_empty
=> true # is_emptyには、trueが代入されている
上記のis_empty = true and false
でfalseを返しているのでis_empty
にfalseが代入されたようにみえますが、and
よりも=
の優先度が高いのでtrueが代入されます。
このようにandは優先度が低く他の演算子の影響を受けてしまうので、基本的には&&
を使用するようにしましょう。
論理否定(NOT)
論理否定(NOT)を表す論理演算子は、!
とnot
です。
1
2
! 式 # ! A
not 式 # not A
基本的には、!
の方を使います。 式(A)が真なら式全体(! 式
)は偽になり、式が偽なら式全体は真になります。
それではサンプルコードでこの挙動を確認しましょう。
論理否定の挙動を確認しよう
Rubyでは偽になる値はnilとfalseだけなので、次のコードの式(10
)の結果は真です。
1
2
irb(main):001:0> ! 10 # ! 式
=> false
そして真は、trueとして扱われるので式全体(! 10
)の結果は偽としてfalseが返ります。逆にfalseを式に指定した場合は、次のようにtrueが返ります。
1
2
irb(main):002:0> ! false # ! 式
=> true
式(false
)の結果は偽なので、式全体(! false
)の結果は真としてtrueが返ります。論理否定の挙動をまとめると、次のようになります。
1
2
3
4
irb(main):001:0> ! true
=> false
irb(main):002:0> ! false
=> true
論理否定の使い所とは?
論理否定は、比較演算子(==, !=, <, >
...)を使用した式を指定することができます。
次のように!
のあとの式は、括弧()
で囲む必要があります。
1
2
3
!(式)
!(1 < 5)
比較演算子の返り値はtrue
かfalse
なので!
を使用すると、次のようになります。
1
2
3
4
irb(main):003:0> 1 < 5
=> true
irb(main):004:0> !(1 < 5)
=> false
(1 < 5)
は真でtrueを返すので、式全体( ! (1 < 5)
)の結果は偽でfalseを返します。
そして、次のように式(5 == 3
)が偽でfalseを返す場合は、式全体( ! (5 == 3)
)の結果は真でtrueを返します。
1
2
3
4
irb(main):006:0> 5 == 3
=> false
irb(main):007:0> !(5 == 3)
=> true
次のようにifの条件式で使用することもできます。
1
2
3
4
5
6
7
number = 5
if !(number == 3) then
puts 'numberはではありません。'
end
# 実行結果 numberは1ではありません。
!(number == 3)
の式全体の結果は真でtrueを返すので、then以下の処理が実行されていますね。
「not」と「!」の違いとは?
not
は、!
と同じ働きをしますが優先順位が低いです。andの優先順位は、他の演算子と比べても低い位置にあるので、and、orと同様に考慮しなければ結果に影響を与える可能性があります。
例えば左辺に!
を指定し&&
と組み合わせた場合の演算結果は、次のようになります。
1
2
irb(main):026:0> ! true && false
=> false
&&
は左辺が偽ならその値を返して真なら右辺の評価結果が返るので、上記では左辺の! true
の結果であるfalseが返ります。notもこの働きは一緒なので同じようにfalseが返ると考えますよね。
しかし、実際には次のコードのようにtrueが返ります。
1
2
irb(main):027:0> not true && false
=> true # falseではなくtrueが返る
not
は&&
よりも優先順位が低いので、true && false
が先に評価されてfalseを返し、次にnot false
が評価されてtrueを返しているのです。
このようにnotは優先度が低く他の演算子の影響を受けてしまうので、基本的には!
を使用するようにしましょう。
優先順位まとめ
演算子の優先順位は次のようになります。
高い ::
[]
+(単項) ! ~
**
-(単項)
* / %
+ -
<< >>
&
| ^
> >= < <=
<=> == === != =~ !~
&&
||
.. ...
?:(条件演算子)
=(+=, -= ... )
not
低い and or
演算子の中で優先順位が低いのは、not、and、orということがわかります。
参考文献:Rubyリファレンスマニュアル 演算子式
論理演算子まとめ
各論理演算子の特徴は、次の表のようにまとめられます。
演算子 | 例 | 意味 | 優先順位 |
---|---|---|---|
|| | A || B | AもしくはBが真のとき真、 どちらも偽のとき偽を返す |
高い |
&& | A && B | AかつBが真のとき真、 それ以外は偽を返す |
高い |
! | !A | Aが真のとき偽、 偽のとき真を返す |
論理演算子の中で1番高い |
or | A or B | ||と同じ | 演算子の中で最も低い |
and | A and B | &&と同じ | 演算子の中で最も低い |
not | not A | !と同じ | 演算子の中で最も低い |
||
と&&
は、式全体の結果として評価された値を返します。
A || B
は、左辺(A)を評価して真ならその値を返し、偽なら右辺(B)の値を返すA && B
は、左辺(A)を評価して偽ならその値を返し、真なら右辺(B)の値を返す
よく使われる論理演算子なので覚えておきましょう。今回のようにRubyの基礎から徹底的に学びたい方は、チェリー本と呼ばれるこちらの参考書が良いでしょう。
この記事のまとめ
- 2つ以上の真偽値を計算して1つの結果を得ることを「論理演算」と呼ぶ
- 論理演算を表す記号のことを「論理演算子」と呼ぶ
- 式は左辺から順番に評価されて、式全体の結果が決まらない場合のみ右辺を評価する(短絡評価)