pasberth/Macra

記号は関数としても定義できるはずなのに関数を定義できる仕様がない

Closed this issue · 20 comments

たとえば

a :!! b

のように :!!!! は関数呼び出しだから、 !! という関数も定義できるはず。

なのにもかかわらず、今はそれを定義できる構文がない。

!define !! f ---- invalid ----

!define の第一引数として !! などの記号を受け入れられるだけでは不十分。
なぜなら

#[ id => val : * -> * -> * = !define id val ]

としても

!! => val

が構文として許されないから。

じゃあ、 x => y の x にも !! を受け入れちゃえば? と言うと

=> => val

のように => を id にしたい場合がパースできない。

prefix として ' を導入するのがいい気がする。

!define '!! f
'!! => val
'=> => val

ごめん。 a :!! b!! 関数じゃなくて :!! 関数の呼び出しだ。

!define ':!! f

こうなるかな。

それだと結局、記号を関数として定義できてないことにならない?
'!!ってa!!とかb!!とかやってるのと変わらない。

案1:
=>はMacraの構文だから使えないってことにする。

案2:
'を特別扱いする必要は全くない。idの始めの文字として/[a-zA-Z']/とかで含めてやればいい。

やまぴくが実際どういう構文にしたいのかイマイチ見えてこない。

!! => val

↑のコードを valid にしたいってことでok?

!! => val を valid にすると、もう !! という構文が他のどこでも使えなくなっちゃうんだよね。

lisp と違ってカッコがないから、単純に !! を identifier として valid にはできない…

案1について:

x => y

は Macra の構文だけど => 関数の呼び出しだから定義できる構文はあるべき。

案2について:

???

その案がつまり、なにをしたいのかよくわからない。

=>とか!!はidとして使えていい。
!! => valをvalidにしたら!!が他で使えなくなるなら
foo => valでfooが使えなくなるの?

案1は勘違いなので気にしないで。

案2は、!!とか=>をidとしてvalidにしない場合の話。
=>は通らないけど、a=>とかx=>とか、記号で始まらないものならidにできるから、別に'を特別視する必要はなくて、単にidが'で開始してもいいことにすればいい。

なるほどね。

!define !! f

はできないけど

!define '!! f

ができれば

a :!! b

はできないけど

a :'!! b

ができるから ' を id にできればいいってことか

id 以外の意味としては、 foo は使えなくなるよ。
たとえばキーワードとして foo は使えない。

!! が id として許されるなら !! は中置関数としては使えない

パースできる事はできると思うけど、汚い仕様(構文がコンフリクトしてる)になるから嫌

!! が id として許されるなら !! は中置関数としては使えない

これは

!! => val

という構文が許されるなら

a !! b

という構文を許す事はできない、という意味ね (コロンがあれば許される) 。

だからこそ今は中置の構文でコロンが必須な訳だけど。

そもそも => 関数呼び出しの構文があるのに => 関数定義の構文がない、
:!! 関数の呼び出しはあるのに :!! 関数定義の構文がない、

という話だから、

たとえば

x => y
x :!! y

のどっちもがマクロ呼び出し専用 (もしマクロ展開されなかったらコンパイルエラー) で
予約語だから identifier としては使えない事にして、
そういう関数を定義したかったら必要だったら普通の identifier に置換してねってことで

#[ x :!! y : * -> * -> * = hogehoge x  y ]

のほうがいいかもしれない。

=>っていつ構文になったの

あとfooと!!の件だけどそれならなんで記号だけ特別扱いするのかがわからない。a-zA-Z0-9と全く同じ扱いにすればいいんじゃないの?

中置は:必須か、もし:なしの演算子を処理系が提供するならそれは予約語にしていいんじゃない?

=>っていつ構文になったの

これは原案からもともと構文だよね (構文上、ほかの記号と違って優先順位があるんだから。)

記号だけ特別扱いするのは、それがあとあと構文として使われるかもしれないからと、
実際どの記号が id に使われるのか仕様が曖昧だから。

a-zA-Z0-9 は構文としてなにか意味を持たせる事がないはずだからそういう扱いになってて、

たとえば #60 で実際に記号に a-zA-Z0-9 と違う意味を持たせる事になったら
記号は id と同じ扱いにはできないよね。だから今は id とまったく同じ意味にはしてない (あとで仕様を変えやすくするため)

記号にはなにか構文上の意味を持たせたいから
まだ id には使えないようにしてる。

仕様が曖昧っていうのは、「記号は id にしていい」とはいっても
空白以外のすべての文字は id にしていいという話にはならなくて、
たとえば # なんかはすでにコンパイル時の処理のために id には使われないべきだし、
,=> も構文上の意味があるんだから id にはできないべき (もちろん頑張ればパースできない事もない)

で、そういうのを省いたぜんぶを id にしていいんじゃないのというと
たしかにパースはできるけどめちゃくちゃ汚い仕様だと思うから
id に使用可能な文字はかなり厳密にしたい。

でもそれはまだ決まってない事だから、とりあえず今は !! は id にはできないことにしてる。

もちろん、 !! を id としてとりたいならそれでもいいけど、
でも「空白以外のすべての文字」という仕様じゃなくて

!? は id として使えるが *+ は使えない、などを厳密に定義したい。

逆に !! など記号すべてを id とまったく同じ扱いにする利点がわからない。
そういうことをしたら記号に構文上の新しい意味を持たせにくくなるから
S式ならともかく、構文の優先順位はとても重要になるはずの Macra では不利だと思う。

もし #60 を採用したら

a !! b

は中置関数として

(!! a b)

という意味になるわけだけど、 !! を id として使える仕様と同時に存在すると

def !! f

のような構文は、ユーザとしては

(def !! f)

と解析されて欲しいけど

(!! def f)

になっちゃって、結局記号は id にできないのと同じ事になるから、どっちかの仕様を捨てなきゃいけない。
安易に記号をぜんぶ id として使えるような仕様にしちゃうとほかの案を採用しにくくなる。

その点

def '!! f

としておけば、どっちも混在できて、構文を増やしやすいよねという話

なるほど、そこで認識がずれてた。記号を特別扱いする明確な理由があるのがわかったので、idとしてvalidにするのはなくしてOK。

'のほうは、'fooはvalid?invalid?

'foo も valid 。

id は原則 'foo' を書かなくちゃいけなくて

a-zA-Z0-9 だけは省略できるというイメージ

とりあえず実装した。

https://github.com/pasberth/Macra/blob/issue59/examples/quoted-symbol.macra

あとはこの仕様で ok なら merge しちゃう

なるほど。いいとおもう

merge した