&& とか || はどんな動作になるか
条件分岐でよく見る&&
や||
はどんな処理をするか完結に説明していきます。
TL;DL
いずれも左側から順に評価をする。
- &&: 評価対象がfalseであればfalseを返す。trueであれば一つ右を評価する。最後まですべてtrueであればtrueを返す。
- ||: 評価対象がtrueであればtrueを返す。falseであれば一つ右を評価する。最後まですべてfalseであればfalseを返す。
それでは早速ソースコードから
今回はGoでサンプルコードを作ってみました。
全容と実行はこちら
func trueReturner() bool {
fmt.Println("trueReturner called")
return true
}
func falseReturner() bool {
fmt.Println("falseReturner called")
return false
}
まずはtrue/falseをそれぞれ返す関数を作成し、関数がコールされたらPrintを実行するようにします。
この関数を使って下のようなコードを動かしてみます。
fmt.Println("======&& test: both true========")
result := trueReturner() && trueReturner()
fmt.Println("result: ", result)
fmt.Println("======&& test: left false========")
result = falseReturner() && trueReturner()
fmt.Println("result: ", result)
こんな感じで&&と||で両方true, 左だけfalseを評価してみます。
この結果は以下のようになります。
======&& test: both true========
trueReturner called
trueReturner called
result: true
======&& test: left false========
falseReturner called
result: false
さて、早速差が見えますね。
両方trueの場合はtrueReturnerが二回コールされていますが、左がfalseの場合はfalseReturnerが一回のみコールされています。
&&は左から評価をして「評価対象がtrueであれば一つ右を評価する。評価対象がfalseならfalseを返す。最後までtrueであればtrueを返す」という動作をになります
右だけfalse, 両方falseのケースを行うと
fmt.Println("======&& test: right false========")
result = trueReturner() && falseReturner()
fmt.Println("result: ", result)
fmt.Println("======&& test: both false========")
result = falseReturner() && falseReturner()
fmt.Println("result: ", result)
を見てみると
======&& test: right false========
trueReturner called
falseReturner called
result: false
======&& test: both false========
falseReturner called
result: false
となります。
左がtrueであれば右を評価する。評価結果がfalseのためresultがfalseになる。
左がfalseであればfalseを返して右は評価をしない。
となっていますね。
ちなみにReactのjsx, tsxでこんな記述ができるのもこの仕組みのためです。
export const Sample = () => {
const someArray = [1, 2, 3, 4, 5];
// return <div>{someArray && someArray.map((item) => <p>{item}</p>)}</div>;
return (
<div>
{someArray.length > 0 && someArray.map((item) => <p>{item}</p>)}
</div>
);
};
この調子で||も見ていきましょう。
fmt.Println("======|| test: both true========")
result = trueReturner() || trueReturner()
fmt.Println("result: ", result)
fmt.Println("======|| test: left false========")
result = falseReturner() || trueReturner()
fmt.Println("result: ", result)
======|| test: both true========
trueReturner called
result: true
======|| test: left false========
falseReturner called
trueReturner called
result: true
両方trueの場合はtrueReturnerが一回のみコールされていますが、左がfalseの場合はfalseReturnerが二回コールされています。
||は左から評価をして「評価対象がfalseであれば一つ右を評価する。評価対象がtrueならtrueを返す。最後までfalseであればfalseを返す」という動作をします。
同様に残りのケースも見ると
fmt.Println("======|| test: right false========")
result = trueReturner() || falseReturner()
fmt.Println("result: ", result)
fmt.Println("======|| test: both false========")
result = falseReturner() || falseReturner()
fmt.Println("result: ", result)
}
======|| test: right false========
trueReturner called
result: true
======|| test: both false========
falseReturner called
falseReturner called
result: false
となります。
ちなみにPythonでも書いてみた
もちろんPythonも同様の動作になります。
def main() -> None:
# test and
print("======and test: both true========")
result = true_returner() and true_returner()
print("result: ", result)
print("======and test: lest false========")
result = false_returner() and true_returner()
print("result: ", result)
print("======and test: right false========")
result = true_returner() and false_returner()
print("result: ", result)
print("======and test: both false========")
result = false_returner() and false_returner()
print("result: ", result)
# test or
print("======or test: both true========")
result = true_returner() or true_returner()
print("result: ", result)
print("======or test: lest false========")
result = false_returner() or true_returner()
print("result: ", result)
print("======or test: right false========")
result = true_returner() or false_returner()
print("result: ", result)
print("======or test: both false========")
result = false_returner() or false_returner()
print("result: ", result)
def true_returner() -> bool:
print("true_returner called")
return True
def false_returner() -> bool:
print("false_returner called")
return False
main()
======and test: both true========
true_print called
true_print called
result: True
======and test: lest false========
false_print called
result: False
======and test: right false========
true_print called
false_print called
result: False
======and test: both false========
false_print called
result: False
======or test: both true========
true_print called
result: True
======or test: lest false========
false_print called
true_print called
result: True
======or test: right false========
true_print called
result: True
======or test: both false========
false_print called
false_print called
result: False