Ruaでエラーハンドラを設定するとこで、妙な違和感があって、少しだけもやもやしていたけど、原因が分かった。
Rua.new(lamda {|e| puts e })
Rua#newにブロックを渡さないで、lambdaでProcを渡しているから妙なごちゃごちゃ感があったんだ。
「じゃあ、まあRua#new {} と書けるようにするかね」と思ったけれど、そこでまた違和感が。newに渡すブロックって初期化処理なような。
ブロックって基本的に渡されるメソッドに紐付く処理を記述する気がするけど、newとエラーハンドラはあんまし関係ない。エラーハンドラはイテレータじゃなくて、ただの引数だ。
コンストラクタでエラーハンドラを渡してもらうようにしたのは、実装上の都合。
RuaとRuaFuncの実体の構造体が
struct rua { lua_State *L; VALUE error_handler; }; struct rua_ref { lua_State *L; VALUE error_handler; };
みたいな感じになってて、RuaFuncが生成されるときにerror_handlerをruaからrua_refにコピーするけど、Ruaインスタンスでエラーハンドラが変更されてRua#evalとRuaFunc#callで違うハンドラが実行されたらヤだなぁ、ということでコンストラクタ以外ではエラーハンドラを渡せないようにした。
それなら、rua_ref側でポインタを持つようにすればいいのかなぁ?
struct rua_ref {
lua_State *L;
VALUE *error_handler;
};