LoginSignup
1
0

何気なく使っている&&, ||の真の意味

Last updated at Posted at 2023-12-09

&& とか || はどんな動作になるか

条件分岐でよく見る&&||はどんな処理をするか完結に説明していきます。

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も同様の動作になります。

main.py
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
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0