2023 03 20 - qnighy/umo GitHub Wiki

近況

特に実装は進んでいない。

宣言と文

次のプログラムでは順序が重要であると考えられ、ある種の文的な構造を持つ。

let x = 1;
let y = x + 1;
let z = y * 2;

次のプログラムでは順序は重要ではなく、ある種の宣言的な構造を持つ。

let f(x) = x <= 0 || !g(x - 1)
let g(x) = !f(x - 1)

これらを各言語はどのようにハンドルしているだろうか?

  • Rubyなどの言語では常に文のような構造を持つ。
  • CやJavaなどの言語では、宣言的な構造を持つ階層と文的な構造を持つ階層が分離されている。 (といいつつCではより実装的な事情から宣言順を考える必要があるが、それはここでは考えない)
  • OCamlでは階層はそれほど分離されていないが、再帰が必要なときは特別な文法を使うようになっている。
  • JavaScriptでは function に特別なhoisting挙動が定義されていて、functionのもつ宣言的な性質が言語仕様として明示的に扱われている。

CやJavaのような分離構造にするとモジュールの初期化でできることに制限ができ、 fn main() {} のような間接的なエントリポイントが必要になる。これはこれで悪くない設計だが、もしモジュール自体を実行可能にしつつ、しかし必要に応じてブロック内でのシャドウイングを可能にするとしたらどうするのがよいだろうか?

このような前提のもとではOCamlのアプローチが比較的堅牢に見えるが、 and を導入する部分に無駄があるようにも感じられる。

let rec f x = ...
and g x = ...
in ...

シンプルに、宣言的なものが並んだときは相互再帰を許すというのでもよいような気もする。またJavaScriptでは以下のような書き方が許されている:

const x = f();
function f() {
  ...
}

これをシャドウイングを持つ言語にも導入してしまうのは悪くない選択肢かもしれない。つまり、各文・宣言はそのブロックで宣言されている全ての宣言的な変数と、その行以降で定義されている全てのlet変数を参照できる (さらに別の変数でシャドウされていない限り)。

このようにしておくと値ではないもの (type aliasなど) も自然に導入できる。ここまで書いていて思ったがシャドウイングの話をした以外はほぼJavaScript/TypeScriptの話になってしまった。