コンテキスト明示関数 続き
昨日の続き。
と、いうわけで、昨日の話をもっとゆる〜い方向へ考えてみる。とりあえず思い付いた案は、対象コンテキストを指定しておけば、関数名のプレフィクスと、引数一個を書かないでもいいようにする、と、いうもの。
まず、コンテキストを定義するときに、プレフィクスを指定できるようにしておく。
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);