純粋関数型システムプログラミング言語Cargryを開発しています
突然ですが、Functional But In-Place (FBIP)と、Local Mutable Before Using (LMBU)をやめます!
なぜやめるのか - FBIP
理由は2つあります
1. KokaのFBIPと異なるから1
FBIPは、「参照カウントが1つしかなく、今後一度も使われない場合は、メモリを解放、及び再利用する」です
そもそも、CargryにはRCはありませんし、定義していたFBIP規則は、関数を跨いでのみ行うものです
2. KokaのFBIPと異なるから2
Kokaでは、FBIPは自動で行われます。対してCargryは、明示的に宣言しなければなりません。動作から違います1
なぜやめるのか - LMBU
単純に曖昧だから
LMBU規則では、実質単純な代入と、可変操作のみを行う関数を呼び出すことしかできません
ですが、実際にコードを書く上で、可変操作を行わない関数も必要です
それができない理由は、参照を作るまでというルールにあります
Cargryの変数はスコープの最後まで生き続けます。そうであれば、参照を取った後に可変操作を行いたくありません。そのためです
代わりにどうするのか
FBIP / LMBUの代替として
- Drop In Pure (DIP)
- Swap In Effect (SIE)
を導入します
DIPについて
まずは、ルールです
- DIP最適化された関数を呼び出していること
- DIP対象の引数(DIP / SIE許可型の引数)に値が渡されていること
- 参照が渡される値に存在しないこと
- 元の値が今後一切使われないこと
Cargryはリソース管理が完全にスコープベースで、永続データなので、非常に効率が悪いです
そのため、スコープの終端より前に破棄できるようにしなくてはなりません
DIPはこれを担当します
SIEについて
まずは、ルールです
- SIE最適化された関数をエフェクトとして呼び出していること
- SIE対象の引数(DIP / SIE許可型の引数)に値が渡されていること
- 参照が渡される値に存在しないこと
こちらは、利便性のためにハンドラ内限定で、再代入を可能にするためのものです
コンパイル時属性によって、無効にできます
終わりに
かなり大きな仕様変更でした。すみません
おまけ
ハンドラ書くの面倒くさい! というわけで、Cargryは次のような言語機能を考えています
Default Handler
プログラマが、デフォルトハンドルを使うことを明示して、そのエフェクトのハンドラを書く手間を省きます
これにはメリットがあります
言語の難易度を下げる
もし、デフォルトハンドラがなければ、ただ文字を出力したいだけなのにコンソールに文字を表示する機能を実装しなければなりません
デフォルトハンドラがあれば、ライブラリ側が用意したハンドラを使うので、これを避けることができます
ライブラリの進化 ≠ コンパイラの進化
デフォルトハンドラがなければ、エントリポイントのmain関数は誰がハンドルするのでしょうか
Cargryはランタイムが存在しないため、コンパイラがすることになりそうです
ですが、ライブラリを新しくする度に、新しいコンパイラをリリースしなければなりません
さらに、main関数で自分の定義したエフェクトを使えません
main関数から、別の関数を呼び出して、その関数をエントリポイントとする他ありません
デフォルトハンドラがあれば、コンパイラはライブラリが定義したハンドラを適用するだけ、ライブラリとコンパイラを分離できます
-
Koka含め、全ての言語をリスペクトしているので... ↩