このブログは、旧・はてなダイアリー「檜山正幸のキマイラ飼育記 メモ編」(http://d.hatena.ne.jp/m-hiyama-memo/)のデータを移行・保存したものであり、今後(2019年1月以降)更新の予定はありません。

今後の更新は、新しいブログ http://m-hiyama-memo.hatenablog.com/ で行います。

CatyScript1+α

昨日、「2010年10月の予定を2012年1月に振り返ると」なんてのを書いて、久々にCatyScript言語仕様について考えたりしている。

1.0とか2.0とか言っても、結局なし崩しに言語仕様が変わっていて、あんまり切れ目はない。今のところ、後方互換性を壊すような変更はしてない。

今後の予定で、慎重に考えたほうがいいのは:

  1. 例外処理: 例外型、throw、try-catch的な構文 http://d.hatena.ne.jp/m-hiyama/20091117/1258449015
  2. undefsafe機能、単なるモナドではない。クライスリ圏のEmbedding-Projection関手ペアを考えるのだと思う。
  3. フォーリンデータ型:よくよく注意しないと、型システムを滅茶苦茶に壊す。

なるべく早く欲しいのは:

  1. beginブロックとrepeat制御
  2. ポートに対するcall, forward

問題はないと思うが別に慌てなくてもいいのは:

  1. 論理パイプ、|&、||
  2. 並行タプル =[,]、={,} http://d.hatena.ne.jp/m-hiyama/20101223/1293077872
  3. unclose構文 http://d.hatena.ne.jp/m-hiyama/20110920/1316512670
  4. 変数参照にパス式、 %foo.a.2.tag() とか。

やらないほうがいいと思うのは、パラメータ構文の拡張。変数参照が使えるので、もはや不足はない。これ以上やるとなんかヤバそうだ。フォーリンデータも相当にヤバいのだが、メタオブジェクトの表現にはないと困るので、入れざるをえない。必要なメタオブジェクト型は:

  1. Type
  2. Code
  3. Command
  4. Module
  5. Ambient

Type(型)とCode(スクリプトのコード)があれば、他はXJSONでも表現できるとも言える。


型システムは言語仕様の一部とも言えるが、いちおう別に考えると:

型の排他性判定は結局はintersectionの計算になる。N個の型が排他であることを保証するのは、(N*(N-1))/2 回のintersection計算をすればいい。今まで簡略でより速い方法を使ってきたが、正面からintersection計算してもいいかもしれない。

intersection計算でネックになるのはスキーマ属性なのだが、これは「できなきゃできないでいい」と割り切るべきだろう。排他性が不明なときは、安全性から「排他じゃない」とみなす。

あとは型推論だが、トランザクション処理をちゃんとすれば、実行時型チェックでもそれほどマズイわけじゃない。コンパイル時にチェックできたほうがいいが、実行時チェックを排除することはどうせできない。

[追記]

今現在の心境では、whenの拡張はやりたくなくなった。どう拡張しても不自然な感じがするからだ。もともとwhenは拡張することを想定して設計したわけじゃなくて、一番簡単な分岐を実現しただけ。実際、概念も実装も簡単で、なかなかに使いやすい。こじんまり良くまとまっているものに手を加えるのはいかがなものか。

汎用的で強力な分岐構文caseを考えてみた。分岐条件は型であり、whenと同様に分岐条件は排他的でないといけない。つまり、互いに排他的なN個の型を並べる。分岐条件を適用する部分をパス式で指定できて、分岐後処理に渡す直前のフィルタリング処理も書ける。

同様な機能を提供する構文が2つあるのはドーヨ?という気はする。caseはwhenの機能を完全に含んでいるので、whenを廃止しても困ることはない。だが、whenは残したい。かなりのところwhenで間に合うし、タグ分岐なら明らかにwhenのほうが書きやすい。

もともと、CatyScriptの制御構造は排他的多方向分岐だけで、それをwhenが担ってきた。が、whenがいささか非力な点が気になってきた。whenの拡張・増強はしないで、別な排他的多方向分岐を入れたほうが良かろう、と、そう思っている。

[/追記]

[追記2]

フォーリンデータ型のなかで、単なるメタオブジェクトというよりはむしろインターフェースと言うべきものがある。eachへの入力となるデータだ。現在、eachの入力はJSON配列/オブジェクトに限っているが、なんつーかIterableともでいうインターフェースを持っていればいい。each{f} の処理を手続き的に書けば:


var output = [];
while (input.hasNext()) {
var item = input.next();
output.push(f(item));
}
return output;

だから、hasNext(), next() を持っているナニカならeachに入れていい。データベースのカーソルとか、ファイルのストリームとか。型Tの配列と見なせるモノを Iterable とすると、Tが既知の型なら eachは Iterable<T> -> list<T> となる。list<T> -> Iterable<T> は暗黙に変換されるから、黙っていても list<T> -> list<T> が実現される仕掛け。

[/追記2]