この記事では、プログラムの実行に
なでしこ3簡易エディタ - 日本語プログラミング言語「なでしこ3」
を用います。
感染症対策
あるイベントの主催者は、感染症対策のため「ノーマスク」または「ワクチン未接種」な人の入場はお断りすることにしました。
マスクを着用しており、ワクチンも接種済みの人は、他に断る理由がなければ入場をお断りしない方針です。
さて、マスクを着用しており、ワクチンも接種済みの人がやってきました。
ノーマスクはいいえ。
ワクチン未接種はいいえ。
もし、ノーマスクまたはワクチン未接種ならば
「お帰りください。」と表示。
違えば
「ようこそ!」と表示。
ここまで
あれ?なぜか追い返してしまいました。
おかしいですね。
続いて、ノーマスクの人がやってきました。
病気などでマスクを着用できないのかもしれないし、もしかしたら過激な活動家かもしれません。
ノーマスクははい。
ワクチン未接種はいいえ。
もし、ノーマスクまたはワクチン未接種ならば
「お帰りください。」と表示。
違えば
「ようこそ!」と表示。
ここまで
あれあれ??今度は方針に反して受け入れてしまいました。
もし他の参加者に迷惑をかける活動家さんだったら大変です。
いったい、どうしてこんなことになってしまうのでしょうか?
調査
値の確認
まずはそれぞれの値を確認してみます。
ノーマスクはいいえ。
ワクチン未接種はいいえ。
ノーマスクを表示。
ワクチン未接種を表示。
「{ノーマスクまたはワクチン未接種}」を表示。
「ノーマスク」も「ワクチン未接種」も 0
であるにもかかわらず、
「ノーマスクまたはワクチン未接種」は true
となっています。
色々なパターン
さらに色々なパターンを試してみました。
ゼロは0。
(0||0) を表示。
(0または0) を表示。
(ゼロ || ゼロ) を表示。
(ゼロ または ゼロ) を表示。
(ゼロ||ゼロ) を表示。
(ゼロまたはゼロ) を表示。
(0またはゼロ) を表示。
(ゼロまたは0) を表示。
(ゼロ またはゼロ) を表示。
式 | 評価結果 |
---|---|
0||0 |
0 |
0または0 |
0 |
ゼロ || ゼロ |
0 |
ゼロ または ゼロ |
0 |
ゼロ||ゼロ |
0 |
ゼロまたはゼロ |
true |
0またはゼロ |
0 |
ゼロまたは0 |
true |
ゼロ またはゼロ |
0 |
どうやら、以下の条件を全て満たすとき、直感に反して評価結果が真になるようです。
-
||
ではなく、または
を使用する - 左辺が即値ではなく変数である
- 左辺と演算子の間に空白が無い
代入説
もしかしたら、「また」を無視または変数の一部とみなし、「は」による代入をしてしまっているかもしれません。
確かめてみました。
ゼロは0。
「イチまた:{イチまた}」を表示。
イチは1。
「イチまた:{イチまた}」を表示。
(イチまたはゼロ) を表示。
イチを表示。
(イチはゼロ) を表示。
イチを表示。
「イチまた:{イチまた}」を表示。
ゼロを表示。
「また」が無視されることはあるものの、「イチまたはゼロ」および「イチはゼロ」を評価した後も変数「イチ」の値は 1
のままで、論理式 (を意図した記述) 中の「または」「は」により代入が行われることはないようでした。
『もし、AがBならば』構文
マニュアルを探っていると、『もし、AがBならば』構文というものを発見しました。
今回は「が」ではなく「は」ですし、「もし」を用いない「表示」でも効いていますが、「また」の無視と合わせるとそれっぽいかもしれません。
さらに、
もし、複数の条件を「(式A)かつ(式B)」や、「(式A)または(式B)」のように並べて記述したい場合、比較式を記述する際、(比較式)のようにカッコで括る必要があります。
という主張もあり、関係していそうです。
猫は2。
(猫は2)を表示。
(猫は22)を表示。
(猫または2)を表示。
(猫または22)を表示。
もし、猫は2ならば
「にゃーん」と表示。
ここまで
確かに、「また」を無視して「は」を等価比較として扱っているような挙動を示しています。
…しかし、「が」は「は」とは異なり、実際に「もし」の中でしか使えないようです。
猫は2。
もし、猫が2ならば
「にゃーん」と表示。
ここまで
(猫が2)を表示。
「それっぽい」気がしたものの、そのものズバリではなかったようです。
ちなみに、「かつ」を試してみると…
ゼロは0。
イチは1。
(0かつ0)を表示。
(0かつ1)を表示。
(1かつ0)を表示。
(1かつ1)を表示。
(ゼロかつゼロ)を表示。
(ゼロかつイチ)を表示。
(イチかつゼロ)を表示。
(イチかつイチ)を表示。
なんと 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の倍数」と表示。
ここまで。
ここまで。
先述の例でも、変数をカッコで括らなくても「かつ」や「または」の前に空白を入れるだけでうまく動いている感じになったし、この主張も本当かどうか怪しいですね。
結論
- 変数の直後に「かつ」や「または」を書くと、直感に反する挙動となる
- 変数と「かつ」や「または」の間に空白を入れることで、これを回避できる
ことはわかりましたが、なぜこうなるのかはわかりませんでした。
いかがでしたか?