コンテキスト明示関数 続き

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

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);