見出し画像

Bracmat入門#4 アトム(atom)のこと バインディング

もう寄り道はしない

概念的なあれはいっぱいありそうなので、文法定義から考える。

<input>           ::= [<expression>] [;<input>]
<expression>      ::=   <white space> <expression> <white space>
                    | [<prefixes>] ( <expression> )
                    | <leaf>
                    | <expression> <binop> <expression>
<leaf>            ::= [<prefixes>] <atom-or-nil>
<atom-or-nil>     ::= <atom> | <nil>
<atom>            ::= "<string>" | <string>
<string>          ::= <character> [<string>]
<character>       ::= any printable character except \ and " | <spec>
<spec>            ::= \a \b \t \n \v \f \r \" \\
<nil>             ::= ""   (or nothing at all, such as in "()")
<binop>           ::= = . , | & : <white space> + * ^ \L \D ' $ _
<prefixes>        ::= <prefix> [<prefixes>]
<prefix>          ::= [ ~ / # < > % @ ` ? ! !!
<white space>     ::= spaces, tabs, new line and form feed characters

見ほれるくらいシンプルだが、<atom>は<leaf>の構成員であり、 "<string>" または<string>を内容とする。stringとはスラッシュとダブルクオート以外のアルファベット、バックスラッシュ付きのアルファベットと記号となっている。<binop>が二項演算子で、<prefix>は接頭辞でこれは重ねられるようだ。<atom>に関係する二項演算子(バイオプ)をまずは見てゆく。

atom=expression 右から左にバインドする

Each time when the value of atom is asked for, a fresh copy of expression is made available.(atomの値が求められるたびに、expressionの新しいコピーが利用可能になります。)

これはビックリ演算子の事だと思うが詳しく書いていない。アトムというのはそういうものだと聞いた記憶もあるので、あとでビックリ演算子の時にもう一度しらべてみる。

expression itself is unchangeable and can only be wiped out by removing the binding between expression and its name, atom. This has, in turn, no influence on the copies made earlier.(expression自体は変更できず、expressionとその名前であるatomの間のバインディングを取り除くことによってのみ消去することができます。これは、以前に作成されたコピーには何の影響も与えません。)

これもいわゆるアトムっぽいことの説明だと思う。とりあえず言われた通りの動かし方をしてみる。

{?} a=atom
{!} a
   S   0,00 sec  (3970.3987)
{?} a
{!} a
   S   0,00 sec  (3970.3987)
{?} !a
{!} atom
   S   0,00 sec  (3969.3987)
{?}

趣向が分かれるかもしれないが、ダブルクオートで文字リテラルのこと考えなくていい世界を夢見ていたので、この感じはいい。少し遠回りに見ていくが、この場合はaは先ほどのアトムではなくcharacterになるので、bにはatomではなくてaというcharacterが入ることになる。

{?} a=atom
{!} a
   S   0,00 sec  (3970.3987)
{?} a
{!} a
   S   0,00 sec  (3970.3987)
{?} !a
{!} atom
   S   0,00 sec  (3969.3987)
{?} b=a
{!} b
   S   0,00 sec  (3972.3989)
{?} !b
{!} a
   S   0,00 sec  (3971.3989)
{?}

これまでこれに何のメリットがあるんだと思っていたが、文字リテラルを使わなくてよくて、式展開みたいなこともこれでできるなら、コスパが良い気がする。本家の解説はこちら

{?} a=2    { create binding }
{!} a
   S
{?} !a:?b  { bind copy to b }
{!} 2
   S
{?} !b     { show b's value }
{!} 2
   S
{?} a=3    { remove a's binding to 2}
{!} a
   S
{?} !b     { show b's value }
{!} 2
   S

バインディング、コピー、などの言葉を覚えておくとよさそう

基本的な二項演算子では+と*があって、除算と減算の記号がないのも、理由として納得がいく。

{?} !a
{!} atom
   S   0,00 sec  (3973.3993)
{?} !c
{!} atom
   S   0,00 sec  (3973.3993)
{?} !a+!c
{!} 2*atom
   S   0,00 sec  (3975.3993)
{?} !a*!c
{!} atom^2
   S   0,00 sec  (3975.3993)

サンプルではあえて、同じキャラクターを別のアトムにバインディングしている。計算するためには!が必要でそうしないとa+cは別のキャラクターとして生まれ変わってしまう。ここがややこしいかもしれないが、後々うま味が出そうな部分だ。*記号が入っているが意味合いとしては代数的に!a+!cは2アトムとなり!a*!cはアトム二乗となる。文字データに的を絞ったことで、代数的な定義が非常に親しみやすくなっている。

とにかく「!」は他の言語の$マークみたいなものだと、覚えちゃいなよユー

パターンマッチングについてそのまま書こうと思ったが、量がありそうなので別に分ける。






お願い致します