Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
camlspotter committed Dec 2, 2017
1 parent 59bbfe8 commit 625615e
Showing 1 changed file with 68 additions and 27 deletions.
95 changes: 68 additions & 27 deletions leopard_syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,54 +57,96 @@ Facebookの中の人は流石にOCamlの文法に慣れ親しんでいる人達
OCamlは現役のML実装の中で最もよくオリジナルのLCF MLの文法を守っているんですよ。
残しているからって綺麗だと言う事ではないんですけど、
`;;`でREPL入力評価の区切りにしたり、`2,3`みたいにタプルにカッコがいらなかったり、
`letrec`があったりするのは1973年頃からの伝統なんですよ。

とくに`;;`はすぐバカにされるのですが、トップレベルの宣言の終了が明示できない言語で、REPLでは複数行のソースコードをコピペして入力してもそのまま動くものってあまり無いですよね。改行のところに`\`を入れなきゃいけなかったり。MLの授業ではエディタに書いた複数行のコードをREPLに入れて挙動を確かめさせたりするので、複数行のコードを改変なしにそのまま入力できるというのは重要な機能なんです。そうするとMLのような宣言終了を明示しない文法の言語ではどうしても宣言終了の記号が必要になります。それに`;;`を使っているんですね。
`letrec`があったりするのは1973年頃からの伝統なのです。

とくに`;;`はすぐバカにされるのですが、
トップレベルの宣言の終了が明示できない言語で、
REPLでは複数行のソースコードをコピペして入力してもそのまま動くものってあまり無いですよね。
改行のところに`\`を入れなきゃいけなかったり。
MLの授業ではエディタに書いた複数行のコードをREPLに入れて挙動を確かめさせたりするので、
複数行のコードを改変なしにそのまま入力できるというのは重要な機能なんです。
そうするとMLのような宣言終了を明示しない文法の言語ではどうしても宣言終了の記号が必要になります。
それに`;;`を使っているんですね。
なぜ`;;`かというと、英語の句読点`:`, `;`, `,`, `.` を使いたいが、
全て出払っているからです。例えば `;` は逐次評価 `e;e` に使われているから
宣言終了には使えません。`.` だと英語だと文の最後に使うものですからちょうど
いいのですけれど、浮動小数点数他に使ってしまっていて使えません。
全て出払っているからです。
例えば `;` は逐次評価 `e;e` に使われているから宣言終了には使えません。
`.` だと英語だと文の最後に使うものですからちょうどいいのですけれど、
浮動小数点数他に使ってしまっていて使えません。
(その「点」PrologやErlangは頑張ってますね。No **pun** intended.)。
となると句読点は全て使い切っていますので一文字では無理ってことになります。
そうなると式を逐次実行するための区切り記号`;`なのですから
`;;`を逐次実行される宣言の区切りにするのはわりと理にかなっていると思うのですが。

# 対岸のReason

じゃあ逆に私にとってReasonの文法はどうなんだ、と言うと、これが全く響かない。
じゃあ逆に私にとってReasonはどうなんだ、と言うと、これが全く響かない。
OCamlネイティブの人にとっては、慣れ親しんでいる文法をよく知らないJavaScript風に
変えただけだし、言語機能も全く同じなので何の価値もありません。`npm`なんか使わないし
知らんガナ…というのが正直なところです。
変えただけだし、言語機能も全く同じなので何の価値もありません。
JavaScriptバックエンドはBuckleScriptもjs_of_ocamlも普通のOCamlから普通に
使えますし、`npm`なんか使わないし知らんガナ…というのが正直なところです。
実際OCamlコミュニティ本流でReasonが話題になることってないし、
みなさんそうなんじゃないでしょうか。

文法では特にOCamlの構造比較`=`がReasonでは`==`
OCamlのポインタ比較`==`がReasonでは`===`になっているのを見たところで
私にはReasonは読めない書けないなと判断しました。ひっかけ問題かよ。
JavaScriptには`==``===`があるから、みたいですけど、
Reasonの`==``===`はOCamlの`=``==`の意味なんだから、どっちにしろ
やばくないですかね。

私はStackOverflowでOCamlタグがついた未解答質問には出来るだけ解答をつけようと
思っているのですが、このところ、質問がReasonで書いてあることが増えてきました。
多分こういうOCamlプログラムなんだろうなとは思っても確信が持てないので
助けてあげられず、せっかく新しいユーザ入ってきてもコミュニティ的に
Reasonの`==``===`はOCamlの`=``==`の意味なんだから、
JavaScriptに寄せたからって意味違うんだしやばくないですかね。

私は日頃StackOverflowでOCamlタグがついた未解答質問には出来るだけ解答を
つけようと思っているのですが、
(だからわりと気軽に質問書いてください。私じゃなくても誰かが答えますから。)
このところ、質問がReasonで書いてあることが増えてきました。
多分こういうOCamlプログラムなんだろうなとは思っても確信が持てないので助けてあげられず、
せっかく新しいユーザ入ってきてもコミュニティ的に
初めから分断されてるんじゃないかと思います。

# OCamlプログラマのための新文法は?

もしReasonがOCamlの文法の醜さを解決しているとしても、もともとOCaml使っている人に
魅力なかったら、その人たちには意味がないですね
もしReasonがOCamlの文法の醜さを解決しているとしても、
もともとOCaml使っている人に魅力なかったら、その人たちにはあまり意味がない
Reasonは関数型言語の文法がどうもという人に受けたのですから、
じゃあ関数型言語の文法に慣れている人のための
新しいOCamlの文法があってもいいんじゃないか、
OCamlの文法に慣れ親しんでいる人のための文法改良ってできないものかしらん、
とは昔から思っていて、今年は暇な時にちょっとそういう事をやっていました。
じゃあ関数型言語の文法に慣れている人のための新しいOCamlの文法があってもいいんじゃないかしらん、と思いまして、
今年は暇な時に昔作ったものを引っ張り出して遊んでいました。
この文章はそれを紹介しようと思って書いているのですが、
まあそれだけ紹介してもつまらんですので、読み物として書いていると、
前置きがどんどん長くなりますね。

## 問題

OCamlの文法は醜いとか言われても美的感覚は主観的なものですから、
特にOCamlの文法に慣れている人には正直どうでもいいです。
それより、OCamlプログラムをガリガリ書いている時に、あっこれは不便だなー
みたいなところで、文法から来る要素を改善した方がいいのかなと思うんです。

終端を書かなくて良い開いた文法と、
終端を明示しなければいけない閉じた文法要素があるのが
わりと美しくないなあと思っています。

関数型言語的な機能に関する構文は`fun ... -> e`, `let ... in ...`, や
`if .. then .. else ..`など、終端を書かなくて良いLCF MLとかISWIMの
「開いた」文法を採用し、
他方、命令型機能に関する構文は`for i=0 to 10 do .. done`
`while .. do .. done`などの「閉じた」文法を採用しています。
さらに、モジュールに関する文法`struct .. end``sig .. end`
今度は閉じています。まあこれはリストなので閉じるのを明示せざるを得ませんが...
開いていたり、閉じていたり、統一感が無い気がします。

開いた文法には

Imperativeな機能に関する構文はdo done などの明示的に閉じる文法
複数の宣言をまとめるモジュールやクラスに関する文法は閉じる

と、見る人が見ると法則があるのですが、どうも受けがよくありません。

特に開いた文法は閉じる文法から入ってきた初心者が必ず引っかかってバグを出します

## 既存研究: CamlP4

実は既にOCamlの文法を変えたものはあってCamlP4のRevised syntaxと言うものが
ありました、が、これは実に使いにくい。たとえば、この見慣れたOCamlプログラム
実はOCamlの文法を変えたものは既にあるのです。
CamlP4のRevised syntaxと言うものが。
が、これは実に使いにくい。たとえば、この見慣れたOCamlプログラム

```ocaml
let rec fold_left f accu l =
Expand All @@ -126,15 +168,14 @@ value rec fold_left f accu l =

こうなります。何だこりゃ。余分についた`[``]`ですが、Haskellの省略可能な`{``}`の記号が変わって省略不可になったものと思えば大体あっています。さらに各宣言の最後は`;`が必須です。Revised syntaxは普段使いとして使いやすいOCamlの文法を提供するのが目的ではなく、OCamlのASTを操作するためのDSLとして作られたもので、文法要素の開始と終了を明示していたるところ「閉じた」文法にすることでquasiquoteを使いやすくなる効果があります。OCamlの普通の文法ではうまく書けないクォートがRevisedだと書けたはずです。でもだからってなんでこんな文法を覚えなきゃいけないの、ということで、CamlP4関連以外では全く使われずに終わりました。

で、Revised syntaxが面倒だったことをみんな覚えているので、誰もOCamlの新しい文法を作ろうという人はあまりいなかったと記憶しています。
で、Revised syntaxが面倒だったという黒歴史をみんな覚えているので、誰もOCamlの新しい文法を作ろうという人はあまりいなかったと記憶しています。

## 既存研究: F#

あ、でもOCamlの外に、OCaml文法の改変として、もう一つありました
OCaml文法の改変としてもう一つありました。OCamlの外に
F# の "light syntax" です。



昔からOCaml周りの人のジョークに、「文法はHaskellで機能はOCamlのOCamlが欲しい」と言うものがあり度々言われていることですから、OCamlの文法が古びていることは否めません。


Expand Down

0 comments on commit 625615e

Please sign in to comment.