コンテキスト明示関数 続き
昨日の続き。
と、いうわけで、昨日の話をもっとゆる〜い方向へ考えてみる。とりあえず思い付いた案は、対象コンテキストを指定しておけば、関数名のプレフィクスと、引数一個を書かないでもいいようにする、と、いうもの。
まず、コンテキストを定義するときに、プレフィクスを指定できるようにしておく。
context NanikaCtxt { prefix: nanika_ ; };
んで、関数の定義のほうは、
NanikaCtxt gen_context( void ); void nanika_func0( ) context NanikaCtxt; void nanika_func1( ) context NanikaCtxt; void nanika_func2( ) context NanikaCtxt;
こんなふうに書けるようにしておく。
こういうふうに書いとくと、
void func ( ) { nanika_func0( ); <- あんまりお勧めできないけど大丈夫 with ( gen_context() ) { >> func0( ); <- 良い nanika_func0を呼び出す >> func1( ); <- 良い are_func( ); <- 良い are_func を呼び出す >> func2( ); <- 良い } }
こんなふうに書けるようにして、「コンテキストを明示すると、書くのが楽ですよ」程度にしておく。僕の気持ちとしては、このぐらいが丁度いいように感じる。
んで、もうちょっとこれを使いやすくして、ある型は、コンテキストっぽいオブジェクトである、と定義できるようにしておく。
/* GtkWidget *はコンテキストっぽい値 */ context gtk_widget_ctxt(GtkWidget *) { prefix: gtk_widget_ };
んで、関数の定義のときに、どの引数が対象なのかを指定できるようにしておく。
void gtk_widget_unparent(GtkWidget *widget) context gtk_widget_ctxt(widget); /* 引数widgetが操作の対象 */ void gtk_widget_show (GtkWidget *widget) context gtk_widget_ctxt(widget); void gtk_widget_show_now(GtkWidget *widget) context gtk_widget_ctxt(widget); void gtk_widget_hide (GtkWidget *widget) context gtk_widget_ctxt(widget);
そうすると、
void func( GtkWidget *w ) { with ( gtk_widget_ctxt(w) ) { >> show( ); /* gtk_widget_show( w ); */ >> hide( ); /* gtk_widget_hide( w ); */ } }
こんなふうに書ける。引数の型から、操作対象が明確な場合は、省略できても良いかもしれない。
void gtk_widget_unparent(GtkWidget *widget) context gtk_widget_ctxt ; /* GtkWidget* の型の引数は一個だけなので void gtk_widget_show (GtkWidget *widget) context gtk_widget_ctxt ; * わざわざ書かなくても良い */
あと、ぱっと思い付くネタとしては、クリーンアップを付けるとか、
context windows_dc( HDC ) { cleanup: (this) { DeleteDC( this ); } } context gl_context { prefix : gl cleanup: { glEnd(); } } gl_context glBegin( mode ); void func( ) { with( glBegin(GL_LINES) ) { >> Vertex3f( ... ); >> Vertex3f( ... ); } /* ここでglEnd(); */ }
特殊化したコンテキストとか?
context gtk_window_ctxt extends gtk_widget_context { prefix: gtk_window_ }; void func( GtkWidget *w) { with ( gtk_window_ctxt(w) ) { >> set_title( "title" ); /* gtk_window_set_title( w, "title" ); */ >> show( ) ; /* gtk_window_showは見つからないので、gtk_widget_show( w ) */ } }
記法については、もうちょっと練ったほうが良いかもしれない。気が向いたら考える。
と、いうような話をしてみたら、「D言語のwithがそんな感じでは?」っていうような話があって、僕としては、「D言語はwithもあるのか…」って感じだったんだけど、それはいいとして、オブジェクト指向的なwithと比べて、どういう利点があるのかについて説明しておく。
まず、一番の利点は、C言語のライブラリに対して、ラッパ無しでそのまま使える機能である、という点。上のgtkやら、libpngやら、…それ以外にぱっと思い付かないけど、まあ、なんかそういうときに便利かもしれんね、という部分。
それと、もう一個、クラス定義をいじるのに比べたら、関数定義いじるだけなので、ちょっとだけ楽なんじゃないか、という点。
そんな感じ。気が向いたら実装してみる。
とりあえず、手元にあったソースで、使ったら有効そうなのを。
/* spidermonkey */ extern JS_PUBLIC_API(JSBool) JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp); extern JS_PUBLIC_API(JSBool) JS_ValueToObject(JSContext *cx, jsval v, JSObject **objp); extern JS_PUBLIC_API(JSFunction *) JS_ValueToFunction(JSContext *cx, jsval v);
/* cairo */ void cairo_destroy (cairo_t *cr); void cairo_save (cairo_t *cr); void cairo_restore (cairo_t *cr);
/* OpenSSL (使ったことないけど) */ void SSL_CTX_free(SSL_CTX *); long SSL_CTX_set_timeout(SSL_CTX *ctx,long t); long SSL_CTX_get_timeout(SSL_CTX *ctx);