Gauche:UndefinedVariableHandler
Shiro(2008/04/19 02:58:11 PDT): undefinedなグローバル変数への参照が起きた時に何かハンドラを起動 できると便利じゃないか、という話題。 はやみずさんのコレ を見て、ああそういうハンドラがあればfallbackとしてコマンドを 起動できるよなあと思った (というかtclshがそういうことをやってる)。
- はやみず (2008/04/19 23:36:39 PDT): そうですね。Rubyのmethod_missingみたいなのがあれば楽だなあ、と思いつつ苦肉の策として$PATHにあるコマンドを調べあげてマクロ生成、とかやっているので。
- koguro(2008/04/20 00:52:37 PDT): うーん、勘違いしているかもしれませんが、グローバル変数への参照がundefinedだった場合に発生する condition を決めておけばいいんじゃないでしょうか(それと、conditionに変数参照時の継続も含めておく)。 ハンドラを使いたい人は自分でguardしてハンドラを起動するようにするとかすれば、起動タイミングや優先度とかで悩まなくていいんじゃないかと思います。
- Shiro(2008/04/20 04:57:50 PDT): Cルーチンの中でundefinedエラーが発生する 可能性があるので、それが発生した時点の継続に戻れるとは限らないんです。 全てSchemeで書いてあれば例外発生→リスタートは単なる継続渡しで いいんですが、Gaucheの場合は間にCコードが挟まるので話が面倒に なっています。
実はこのアイディアは過去に何度か出てるんだけど、 以下に述べるissueが未解決のため進んでない。 まあ良い機会だからまとめとく。
issues
ハンドラの起動タイミング
ハンドラはどこに所属すべきか。プロセスグローバルにすると モジュラリティが無くなるのでだめ。一番素直なのはモジュールに 付属させること。そしたら、「そのモジュールがvisibleな環境で ハンドラが有効になる」とできるのでいい感じ。
しかし、どのタイミングでハンドラを起動するか。
「そのモジュールを探しに行った時」というのは性能の点で無理。 Gauche:VMの最適化の過去ログのどっかに書いた気がするけど、 モジュール探索チェインの中間のモジュールの探索コストというのは コンパイル時間にシビアな影響を与える (ほとんどのグローバル束縛は 探索チェインをかなりたどった先で見つかるため)。
なので、一度探索を終えて見つからないことがわかってからでないと ハンドラは起動できない。
ハンドラの優先順
で、未定義のグローバル束縛であることがわかったとして、 探索パス中の複数のモジュールでハンドラが定義されていた場合に どれを起動すべきだろうか。
まあ素直に考えれば普通の探索順と同じ順序で探してって最初に 見つかったやつにすればいいんだけど、 普通のグローバル束縛と違って「見えない束縛」だから ちょっと気持ち悪いところがある。
普通の(ハンドラの無い)モジュールaとbがあって、両者がexportしている 名前が重なってないと分かっている場合 (通常の使用の多くの場面では 名前の衝突が無いことを人が確認するのは易しいし、それをチェックする ツールを作るのも難しくない)、aとbをuseする順番はどうでも良い。
ところが、aとbの両方が未定義束縛ハンドラを持っている場合、 useする順番によってどっちのハンドラが呼ばれるかが違ってくる可能性が あるわけだ。
aとbが直接ハンドラを定義するのではなく、ハンドラを定義している 別のモジュールをextendしてたりすると、さらにわかりづらくなる。
ハンドラの安全性
あと、グローバル束縛解決のタイミングでSchemeコードの評価が 起きるのが安全かどうか、要検討。 今でもエラーが投げられる可能性は考慮してるわけだけど、 任意のSchemeコードの評価を許すと継続がらみとかいろいろ トリッキーな状況が生じる可能性あり。
まてよ。でも今でもautoloadだと束縛解決中にSchemeコード評価が 起きる可能性があるんだから、同じように処理すればいいのかな? まだちゃんと考えてない。