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

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

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

## TL;DL

いずれも左側から順に評価をする。

- &&: 評価対象がfalseであればfalseを返す。trueであれば一つ右を評価する。最後まですべてtrueであればtrueを返す。
- ||: 評価対象がtrueであればtrueを返す。falseであれば一つ右を評価する。最後まですべてfalseであればfalseを返す。

## それでは早速ソースコードから

今回はGoでサンプルコードを作ってみました。

全容と実行は[こちら](https://go.dev/play/p/BUNNpVJsdY4)

```go
func trueReturner() bool {
	fmt.Println("trueReturner called")
	return true
}

func falseReturner() bool {
	fmt.Println("falseReturner called")
	return false
}
```

まずはtrue/falseをそれぞれ返す関数を作成し、関数がコールされたらPrintを実行するようにします。
この関数を使って下のようなコードを動かしてみます。

```go
	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のケースを行うと

```go
	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でこんな記述ができるのもこの仕組みのためです。

```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>
  );
};
```

この調子で||も見ていきましょう。


```go
	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を返す」という動作をします。

同様に残りのケースも見ると

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

```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
```