こんばんは。今日は、月1言語企画の一環として作成したプログラミング言語Funtomを紹介したいと思います。
というか、ついさっきプロトタイプができたばかりなんですが。
基本的には、ほぼ自作のプログラミング言語Klassic
をベースにしたのですが、一つやや特徴的な機能があります。それは、まだ存在してないけど名前は決まっている関数を呼び出すことができるというものです。幽霊呼び出し(Phantom Call
)という厨二ぽい名前を付けてみましたが、使い方は以下のような感じです。
def myMap(xs, f) = { ?implementLater(xs, f) } myMap([1 2 3], (x) => x * 2)
ここでは、関数myMap
を実装しているのですが、「後で実装するよ」って旨を表現したいので、それを?implementLater(xs, f)
と記述しています。このプログラムを実行すると、
Exception in thread "main" com.github.funtom.runtime.PhantomCallError: Phantom implementLater([1, 2, 3], <function value>) is called: 2, 3
て感じで、付けられた仮の関数名と実引数を伴った例外が投げられます。幽霊呼び出しの型は今の所必ず'a
みたいな多相型になっていて、式が書ける場所にならどこにでも埋め込めます。ちなみに、Klassicをベースにしているので、型システムはHindley-Milnerの拡張(ぽい)ものです。
で、なんでこれを実装したかなんですが、動的型付き言語の利点の一つとして、実装途中のプログラムでも実行できるというのが挙げられるというのが背景にあります。実行パスによって、エラーが出る場合でもとりあえず途中までは実行できるってやつですね。その利点を静的型付き言語に部分的に取り込めないかというのがこの試みです。実際、条件分岐で、絶対に実行されないパスに幽霊呼び出しを置くと、何事もなく実行ができます。
この機能はネタというか実際問題かなり欲しいものだったりします。特に、静的型付き言語で、「後で実装する」を表現するのに undefined
とか ToDo()
とか ???
とか、bottom typeを返す特別な関数を組み込みで定義(あるいはユーザー定義)してる言語は最近多いと思うんですが、そのへんをもうちょいカジュアルにやりたいのと、どういう実引数と名前で呼び出されたかの情報が欲しいのです。もちろん、Dynamicとかなんか、細工してそれぽく見せる方法は最近のメタプログラミングが強力な言語だと色々あると思うんですが、そういう小細工じゃなくて言語の組み込みでほしいってのが正直な気持ちです。
なお、幽霊呼び出しは実際に呼び出されると必ず例外を吐くわけですが、この辺は、対応する実装が定義されていたら、実行されるみたいな機能も盛り込むともっと面白いかなと思っています(機能的には、幽霊呼び出しに対して、実装が存在するかルックアップするだけなので小一時間あればできそう)。
これが2020年2月分の言語なので、4月中にあと2言語(3月分と4月分)を作らないといけないわけですが(と自分で決めたので)、なんか適当にネタを考えてみることにします。