[LSP42] CofeeScriptとTypeScriptとDart
(この記事はLISP Implementation Advent Calendar 8日目のためのエントリです。)
CoffeeScriptとTypeScriptとDartでLISPを作りました。
https://github.com/zick/CoffeeLisp
https://github.com/zick/TypeLisp
https://github.com/zick/DartLisp
どれもJavaScriptに変換可能でブラウザで実行できる言語です。ただし、Dartは独自のVMも持っています。
動機
今年の春、訳あって42個のプログラミング言語でLISP処理系を実装することになりました。これはその11〜13つ目です。
CoffeeScript、TypeScript、Dartという言語を選んだのはJavaScriptの派生(?)言語ということで非常に簡単そうだったからです。正直これらJavaScript系言語は簡単すぎるので敬遠していたのですが、42個中10個の言語で実装するだけで既に7週間程度を費やしていたため、これはもう少しスピードアップしようと思い、久しぶりに一日で3つの言語でLISPを実装しました。
CoffeeScriptの思い出
PythonとJavaScriptを混ぜたような感じです。インデントでブロックを表し、タイプ数が少なくてすむような文法です。例によってテーブル(JavaScript系の言語なので恐らくオブジェクト?)を使ってLISPのデータ構造を表しました。
makeCons = (a, d) -> { tag: 'cons', car: a, cdr: d }
TypeScriptの思い出
CoffeeScriptが独自の文法なのに対し、TypeScriptはJavaScriptのスーパーセットとなっています。名前が表す通り、変数や関数に型をつけることができます。型は optional なのですが、型をつけなければ完全にJavaScriptになってしまうため、頑張って型をつけました。
// tag は必須、後のデータはあってもなくてもいい interface LObj { tag: string; str?: string; num?: number; car?: LObj; cdr?: LObj; fn?: (args: LObj) => LObj; args?: LObj; body?: LObj; env?: LObj; } function makeCons(a: LObj, d: LObj) { return { tag: 'cons', car: a, cdr: d }; }
ひたすらに色んな所に LObj と書くだけの簡単なお仕事でした。実質的に型付けの恩恵を受けれない上に、やたらとタイプ数が増えるだけの悲しい思いをしました。CoffeeScriptの後だったので、 function と書くだけでも面倒だったのに。あとコンパイル時間が長いのもいただけない。
Dartの思い出
DartはCoffeeScriptと同様に独自の文法を持っています。ブロックは中括弧{}で表し、セミコロンも必要なため、CoffeeScriptと比べるとタイプ数は多くなりますが、それでもイマドキの言語らしく、少ないタイプ数で色々できます。例によってテーブル(Dartの言葉だとmap)を使ってLISPのデータ構造を表現しました。
makeCons(a, d) => { 'tag': 'cons', 'car': a, 'cdr': d };
が、完成品を走らせてみるとCoffeeScriptとTypeScriptと比べびっくりするくらい遅い。ちょっと遅いというレベルではなく圧倒的に遅い。「なんでこんなに遅いの?」と疑問を書いたらDartの中の人から「クラスを使うんだ!」というメッセージとともにパッチが送られてきました。
class Cons { var car; var cdr; Cons(this.car, this.cdr); } makeCons(a, d) => new Cons(a, d);
こんどはDartが圧倒的に速いという結果に。でも中の人にアドバイスを貰ったのはちょっと反則気味な気も。
小学生並みの感想
みんなちがって、みんないい、わけでもない。
[…] CoffeeScriptで書いたLISPを、LiveScriptとして動かしてみたら、途中まで動いてエラーを吐いて止まりました。エラーメッセジを見て修正、というのを3回ほどしたら完全に動いてしまいました […]
[…] 対数グラフであることに注意してください。 トップはCoffeScriptの0.002秒。続いてOCamlの0.007秒。そして3位はなんとOberon-2の0.01秒です。 最下位はEの33.311秒、そしてCeylonの18.358秒、Scratchの6.2 […]
[…] Lisp in TypeScript. It is the pioneering TypeLisp [github.com] of 416 lines described in ” [LSP42] CofeeScriptとTypeScriptとDart ” (“[LSP42] CoffeeScript to TypeScript to Dart”, (Lisp in) CoffeeScript, […]