なでしこさんは論理が苦手？

この記事では、プログラムの実行に
[なでしこ3簡易エディタ - 日本語プログラミング言語「なでしこ3」](https://nadesi.com/doc3/index.php?%E3%81%AA%E3%81%A7%E3%81%97%E3%81%933%E7%B0%A1%E6%98%93%E3%82%A8%E3%83%87%E3%82%A3%E3%82%BF)
を用います。

# 感染症対策

あるイベントの主催者は、感染症対策のため「ノーマスク」または「ワクチン未接種」な人の入場はお断りすることにしました。
マスクを着用しており、ワクチンも接種済みの人は、他に断る理由がなければ入場をお断りしない方針です。

さて、マスクを着用しており、ワクチンも接種済みの人がやってきました。

```
ノーマスクはいいえ。
ワクチン未接種はいいえ。

もし、ノーマスクまたはワクチン未接種ならば
　「お帰りください。」と表示。
違えば
　「ようこそ！」と表示。
ここまで
```

![感染症対策 実行結果1](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/47d37153-7c1d-d33f-db36-6724b11d852c.png)

あれ？なぜか追い返してしまいました。
おかしいですね。

続いて、ノーマスクの人がやってきました。
病気などでマスクを着用できないのかもしれないし、もしかしたら過激な活動家かもしれません。

```
ノーマスクははい。
ワクチン未接種はいいえ。

もし、ノーマスクまたはワクチン未接種ならば
　「お帰りください。」と表示。
違えば
　「ようこそ！」と表示。
ここまで
```

![感染症対策 実行結果2](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/6660bc09-0408-5f3d-6fc1-43265f45441f.png)

あれあれ？？今度は方針に反して受け入れてしまいました。
もし他の参加者に迷惑をかける活動家さんだったら大変です。

いったい、どうしてこんなことになってしまうのでしょうか？

# 調査

## 値の確認

まずはそれぞれの値を確認してみます。

```
ノーマスクはいいえ。
ワクチン未接種はいいえ。

ノーマスクを表示。
ワクチン未接種を表示。
「{ノーマスクまたはワクチン未接種}」を表示。
```

![値の確認](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/b49fddc5-c498-b8ba-3e07-ee0ad7092965.png)

「ノーマスク」も「ワクチン未接種」も `0` であるにもかかわらず、
「ノーマスクまたはワクチン未接種」は `true` となっています。

## 色々なパターン

さらに色々なパターンを試してみました。

```
ゼロは0。

(0||0) を表示。
(0または0) を表示。
(ゼロ || ゼロ) を表示。
(ゼロ または ゼロ) を表示。
(ゼロ||ゼロ) を表示。
(ゼロまたはゼロ) を表示。
(0またはゼロ) を表示。
(ゼロまたは0) を表示。
(ゼロ またはゼロ) を表示。
```

<table>
<tr><th>式</th><th>評価結果</th></tr>
<tr><td><code>0||0</code></td><td>0</td></tr>
<tr><td><code>0または0</code></td><td>0</td></tr>
<tr><td><code>ゼロ || ゼロ</code></td><td>0</td></tr>
<tr><td><code>ゼロ または ゼロ</code></td><td>0</td></tr>
<tr><td><code>ゼロ||ゼロ</code></td><td>0</td></tr>
<tr><td><code>ゼロまたはゼロ</code></td><td>true</td></tr>
<tr><td><code>0またはゼロ</code></td><td>0</td></tr>
<tr><td><code>ゼロまたは0</code></td><td>true</td></tr>
<tr><td><code>ゼロ またはゼロ</code></td><td>0</td></tr>
</table>

どうやら、以下の条件を全て満たすとき、直感に反して評価結果が真になるようです。

* `||` ではなく、`または` を使用する
* 左辺が即値ではなく変数である
* 左辺と演算子の間に空白が無い

## 代入説

もしかしたら、「また」を無視または変数の一部とみなし、「は」による代入をしてしまっているかもしれません。
確かめてみました。

```
ゼロは0。
「イチまた：{イチまた}」を表示。
イチは1。
「イチまた：{イチまた}」を表示。
(イチまたはゼロ) を表示。
イチを表示。
(イチはゼロ) を表示。
イチを表示。
「イチまた：{イチまた}」を表示。
ゼロを表示。
```

![代入テスト](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/a2a1cb63-59f5-48d3-c36a-2df839782606.png)

「また」が無視されることはあるものの、「イチまたはゼロ」および「イチはゼロ」を評価した後も変数「イチ」の値は `1` のままで、論理式 (を意図した記述) 中の「または」「は」により代入が行われることはないようでした。

## 『もし、AがBならば』構文

マニュアルを探っていると、[『もし、AがBならば』構文](https://nadesi.com/v3/doc/index.php?%E6%96%87%E6%B3%95%2F%E3%82%82%E3%81%97&show#hcba3e889)というものを発見しました。
今回は「が」ではなく「は」ですし、「もし」を用いない「表示」でも効いていますが、「また」の無視と合わせるとそれっぽいかもしれません。
さらに、

> もし、複数の条件を「（式A）かつ（式B）」や、「（式A）または（式B）」のように並べて記述したい場合、比較式を記述する際、（比較式）のようにカッコで括る必要があります。

という主張もあり、関係していそうです。

```
猫は2。
(猫は2)を表示。
(猫は22)を表示。
(猫または2)を表示。
(猫または22)を表示。

もし、猫は2ならば
　「にゃーん」と表示。
ここまで
```

![『もし、AがBならば』構文テスト](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/0da6cf14-9d6e-761e-080a-e18ee159612d.png)

確かに、「また」を無視して「は」を等価比較として扱っているような挙動を示しています。

…しかし、「が」は「は」とは異なり、実際に「もし」の中でしか使えないようです。

```
猫は2。

もし、猫が2ならば
　「にゃーん」と表示。
ここまで

(猫が2)を表示。
```

![『もし、AがBならば』構文テスト 2](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/af360ed0-612e-f539-a87f-c461853f8993.png)

「それっぽい」気がしたものの、そのものズバリではなかったようです。

ちなみに、「かつ」を試してみると…

```
ゼロは0。
イチは1。

(0かつ0)を表示。
(0かつ1)を表示。
(1かつ0)を表示。
(1かつ1)を表示。
(ゼロかつゼロ)を表示。
(ゼロかつイチ)を表示。
(イチかつゼロ)を表示。
(イチかつイチ)を表示。
```

![「かつ」テスト](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/a5c456b9-04fb-bfdc-7525-714884c412fd.png)

なんと `undefined` になってしまいました。
また別の現象が起きているようですが、直感に反するということは共通しています。

なお、

> もし、複数の条件を「（式A）かつ（式B）」や、「（式A）または（式B）」のように並べて記述したい場合、比較式を記述する際、（比較式）のようにカッコで括る必要があります。

という主張に続いて掲載されている

> ```
> # 比較式を複数記述したい場合はカッコで括ってください
> A=5
> もし(A%3＝0)または(A%5＝0)ならば
> 　　「3の倍数または5の倍数」と表示。
> ここまで。
> ```

というサンプルは、カッコを外してもうまく動くように見えます。

```
20回繰り返す
　　Aは回数。
　　もしA%3＝0またはA%5＝0ならば
　　　　「{A}は3の倍数または5の倍数」と表示。
　　ここまで。
ここまで。
```

![サンプルのカッコを外してみるテスト](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/6e546215-4579-a6ab-8a89-e9d8aab78e9f.png)

先述の例でも、変数をカッコで括らなくても「かつ」や「または」の前に空白を入れるだけでうまく動いている感じになったし、この主張も本当かどうか怪しいですね。

# 結論

* 変数の直後に「かつ」や「または」を書くと、直感に反する挙動となる
* 変数と「かつ」や「または」の間に空白を入れることで、これを回避できる

ことはわかりましたが、なぜこうなるのかはわかりませんでした。
いかがでしたか？