📈Bracmat入門#6 バイオペ(二項演算子)応用編 &(アンパサンド)と`(バックチック)さらばIF文
これまで「=」と「:」について二項演算子をみてきた。
アンパサンド
サンプルを見ると&の使い方がかなりスマートなようなので、ソース例から働きを見ていきたい。
再掲だが、基本構文ではないが、頻出構文で以下があってほとんど全部&が使われている
WHILE a DO b;
whl'(!a&`!b)
DO b WHILE a;
whl'(`!b&!a)
DO b UNTIL a;
whl'(`!b&~!a)
FOR i := m TO n DO b;
!m+-1:?i&whl'(1+!i:~>!n:?i&`!b);
Selection:
IF a THEN b ELSE c;
!a&`!b|!c;
v := IF a THEN b ELSE c;
(!a&`!b|`!c):?v (works even if !c fails)
SELECT a WHEN c1 : b1 WHEN c2 : b2 OTHERWISE bx;
!a:(!c1&`!b1|!c2&`!b2|?&!bx);
IF文が一番理解しやすそう。
IF a THEN b ELSE c;
!a&`!b|!c;
とにかく短すぎる、つねに条件式については&とセットで「`」が使われているようなので、その意味を調べてみたらよさそう。ちなみに「`」は「'」とは別の記号です💦それぞれバックティック、シングルクオートとかいう
pacifier またはbacktrac
pacifier(おしゃぶり)と呼ばれる接頭辞は、&の一方にはどうも必ずつけて再帰的な動きの最適化を図るようだった。決めの問題で、これでIF文に別れを告げられるのならば別に良い気もするが。
(`!a & !b) !b is always evaluated. (sequence)
(`!a | !b) !b is not evaluated. (useless in this form)
バッククオートに入れると必ず!aは真になるということのようだ。
↘`か↙‘で働きが違うから気を付けよう!
とりあえず、検証するのに、アトムの中身がすぐ見れた方が良い。アトムa b cにそれぞれ1 2 3をいれた。スペースで区切れば別のアトムとしてみてくれる。
{?} !a !b !c
{!} 1 2 3
S 0,00 sec (3971.3988.0)
この前提で、アンドの結果についてみてみる
{?} !a & !b
{!} 2
S 0,00 sec (3969.3988.0)
{?} !b & !a
{!} 1
S 0,00 sec (3969.3988.0)
{?} !a & !c
{!} 3
S 0,00 sec (3969.3988.0)
{?} !c & !a
{!} 1
S 0,00 sec (3969.3988.0)
結果としては、後ろのほうが採用されるということになる。普通の論理積とは違う動きな気がする。
左辺が真なら右辺が返る?
もともこもないが、そうすれば、処理が右側に移れる気もする。先ほどの例はすべて真(S)&真(S)の結果だったが、ここで何のバインディングしていない!d(F)というのを登場させる。falseもしくはjavascript的にはundefinedやらnullやらそういう状態に覚えばよい。
{?} !d
F (3969.3988.0)
バインディング(アサインメント)されてないと、結果はFになる。
{?} !d & !b
F (3969.3988.0)
アトムdがF(偽)だと、「次にいけない」ので、結果は!bになる。ちなみに、もう少し先で見るが 「|」(or)だと、「次にいける」ので結果はFにはならない。
{?} !d | !b
{!} 2
S 0,00 sec (3969.3988.0)
おしゃぶりは「すべてを真に」する?
バックトラックという概念をもう少し見ないと分からないがとにかく結果はこうなる。
{?} `!d & !b
{!} 2
S 0,00 sec (3969.3988.0)
無かったことにするのか、無理やり真にするのかはおいておいて、IF文の実現や滞りなくwhileループするために、この記号が必要なのはなんとなくわかる。
三つつなげて、みてみよう
「!」と書きながら、心の中でダラーとつぶやいている日々
{?} !a & !b & !c
{!} 3
S 0,00 sec (3969.3988.0)
{?} !a & `!b & !c
{!} 3
S 0,00 sec (3969.3988.0)
{?} !a & !b & `!c
{!} `3
S 0,00 sec (3970.3988.0)
とりあえず&は真なら右辺を返すというルールは分かった。バックティックの正体はまだはっきりとはしないが
{?} !a & !b & `!c
{!} `3
S 0,00 sec (3970.3988.0)
{?} `!a
{!} `1
S 0,00 sec (3970.3988.0)
{?} 1!a
{!} 1!a
S 0,00 sec (3970.3988.0)
{?} d!a
{!} d!a
S 0,00 sec (3970.3988.0)
{?} `a
{!} `a
S 0,00 sec (3970.3988.0)
{?} !`a
{!} `1
S 0,00 sec (3970.3988.0)
{?}
普通のキャラクターとは、位置によって立ち回りが違うみたい、とは覚えておこう。
IF THENが無い、ネストもない、けれど可能性は無限大
必要性のない人には、なぜ構造的に便利なネストを手放せばならないのかと疑問に思うかもしれない。しかし、ニッチな事情で私はネストしないで制御構造が書きたいと思っていたので、この考え方は大いに参考になった。SNOBOLとかICONという言語にバックトラッキングという考えがあり、その影響があるみたいだった。少し調べてみてもいいかもしれない。
SnobolとIconは、文字列処理やパターンマッチングに強力な機能を持つプログラム言語です。両方の言語には、バックトラッキングという機能が組み込まれており、これを用いて複雑なパターンマッチングや探索問題を解決することができます。
Snobol:
Snobolは、1960年代にBell Labsで開発されました。
文字列パターンマッチングに特化しており、成功または失敗を返すマッチオペレーションが中心です。
マッチングの際に、一致しない場合は自動的にバックトラックを行い、他の可能性のあるマッチを探します。
Icon:
Iconは、Snobolの後継として1970年代に開発されました。
Iconの特徴的な部分は、「成功」や「失敗」といった結果を返す「目標指向の評価」です。
バックトラッキングは、式の評価が失敗したときに、以前の状態に戻って再評価を行う形で動作します。これにより、異なる結果を生成することができます。
バックトラッキングは、上述のように、探索問題やパターンマッチングでの解の探索に非常に有用です。IconやSnobolのような言語では、このバックトラッキングを言語レベルでサポートしており、その結果、文字列処理やパターンマッチングタスクを非常に効率的に行うことができます。