3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

この記事では、プログラムの実行に
なでしこ3簡易エディタ - 日本語プログラミング言語「なでしこ3」
を用います。

感染症対策

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

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

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

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

感染症対策 実行結果1

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

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

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

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

感染症対策 実行結果2

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

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

調査

値の確認

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

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

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

値の確認

「ノーマスク」も「ワクチン未接種」も 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ならば
 「にゃーん」と表示。
ここまで

『もし、AがBならば』構文テスト

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

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

猫は2。

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

(猫が2)を表示。

『もし、AがBならば』構文テスト 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の倍数」と表示。
  ここまで。
ここまで。

サンプルのカッコを外してみるテスト

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

結論

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

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

3
0
2

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
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?