2週間ぶりの更新となります、スクリプト担当の吉原です。
先週は風邪でお休みしてました。
先々週より熱が下がらず寝込み続けること1週間半…
仕事休む訳にもいかず、ガクガクしながら仕事して、帰ってぶっ倒れての繰り返しの日々。
こういう時は、えてしてロクな事を考えないものですので直ってもしばらくナーバスになってました。
んなこたどーでもいいですね。本日の本題に入ります。
回復後、それまで打っていたNScripterのスクリプトを見直して思ったことなど…
恐らく最長の記事になる予感。
【 NScripterにおける構造体の代替案について 】
他のプログラミング言語などでよく用いられる構造体のしくみをNScripterで再現するのに文字列変数と
split命令を使用する手法は、マニュアルにも書いてありますので有名な話です。
しかし、split命令で切り分けたデータを変数に格納するだけでは構造体の代替としては不十分すぎる。
そう思った方いませんでしょうか?
一つ例としてあげますと、画像の設置座標とファイル名を管理するスクリプトを以下のようにすると…
mov $Object1,”100/200/sample.bmp”
split $Object1,”/”,%Object_X,%Object_Y,$Object_FileName
%Object_X,%Object_Y,$Object_FileNameがそれぞれObject構造体のメンバに当たりますが、
直接変数に触っているとメンバにアクセスしている気がしません。ええ、これは感情論ですけどね。
例では変数名の頭を統一してそれっぽくしてますがそれもなんだかなぁ…
感情論を抜きにしてナンセンスな部分があります。メンバ内のデータを書き換える際とか。
メンバ変数に直接アクセスしてる訳ですから書き換え自体は可能なんですが…。
でもそれなら、そもそも$Object1を細切りする必要すらないんじゃないかと思いました。
直接メンバに当たる変数に代入するほうが手っ取り早いという訳です。
そうしますとメンバ同士の関連が無く、構造体の代替では無くなります。
ですがsplit命令で切り分けた変数をいじくりまわす場合でも、データの関連性は切り分けるときのみ保証されるだけでそれ以降メンバのデータをいじるたび、関連性の保証についてスクリプタがわざわざ意識しなければなりません。
結局、ただ文字列変数を構造体の代替に使用してもメンバ同士の関連性は保証されない。
ならば、関連を保証するルールを「スクリプタ自身が持つ」か「スクリプトに持たせる」しかないのですがそれならば、せっかくですからより良い構造体の代替案を考えてみます。
配列の要素に、メンバとする変数番号を格納し間接参照するなどはどうでしょうか?
すると、先ほどの例でのメンバ%Object_Xはこうなります。
%?Object[m_x] ;m_xは要素番号のエイリアス。参照先のメンバを分かりやすくするためのもの。
C言語的に書くと
Object->m_x;
…記述的には近くなっているし、Object配列を用いるだけならメンバの関連性も配列によって保たれるのではないかと。
クラスにおけるメソッドのようなものも、関数名の頭を統一し残りをメンバにもたせれば、以下のような形で使用できます。
gosub “*func” + $?Object[m_func1]
$?Object[m_func1]が”00″なら、*func00を呼び出します。
この方法はC++ではなくCにおいてオブジェクト指向型プログラミングを行うための仕組みを参考にしました。
これなら、構造体どころかクラスの代替にもなるじゃないか! やったよパパ明日はホームランだ!!
…そう思っていた時期が僕にもありました。
結局「型」として定義できない以上、この方法をとっても同一の構造体型、クラスによるインスタンスを複数生成とかできないんですよね。
インスタンスの数だけこの配列を仕込んでおくとか考えましたが、オブジェクトが100個近くなるともう無理ですね。
各メンバを文字列に統合してリストに保存、ゲッターとセッターを同一オブジェクトで共有する形で用意し、
それらの引数をインスタンスID、メンバなどにして、メンバにアクセスする度にリスト内の対象を分割、統合を行う…
解決案としてこんな方法も考えてもみましたが、アクセス時のコストが高い上、安定して動くまで持っていくだけの労力に見合うような効果があるのか甚だ疑問です。
ポインタ配列に文字列変数の切り分け、この辺の手法の組み合わせ自体は面白い試みだと思うのですが、
僕の頭ではこの辺が限界です。