[back]

【雑記】
2006/10/31 何かが違う...


クラスの機能もほぼ実装が終わり、ファイナライザ実行やdll呼び出しもつけてみた、COM呼び出しはまだ旧バージョンから移植していないが、これについてもすぐ動くだろう、だが、、、


function string(n){
    r="";
    for(i=0; i < n; ++i) r+='\0';
    return r;
}

class File{
    fp=0;

    _fputs  = dllfunc("msvcrt.dll", "fputs",    "cdecl",    "int",  "string, uint");
    _fgets  = dllfunc("msvcrt.dll", "fgets",    "cdecl",    "uint", "binary, int, uint");
    _fopen  = dllfunc("msvcrt.dll", "fopen",    "cdecl",    "uint", "string, string");
    _fclose = dllfunc("msvcrt.dll", "fclose",   "cdecl",    "int",  "uint");

    function close(){
        if(fp)  _fclose(fp);
        fp=0;
    }
    function open(fname, mode){
        close();
        fp=_fopen(fname,mode);
        return (fp)? true : false;
    }
    function gets(){
        if(!fp) return null;
        buff=string(256);
        return (0==_fgets(buff,256,fp))? null : buff;
    }
    function puts(s){
        if(!fp) return;
        _fputs(s,fp);
    }

    function _final(){
        if(fp){
            print("\awarning: File not closed");
            close();
        }
    }
}

/*-------------------------------*/
//テスト用
f=new File();
#if 0
    f.open("test1.txt","w");
    f.puts("Hello world!!\n");
    f.puts("Are you happy?\n");
#else
    f.open("test1.txt","r") || error("Cannot open input file");
    while(s=f.gets()){
        print(s);
    }
#endif
f.close();

となるワケだが、、、何かが違う気がする、これではまるでプログラム言語みたいだ. 真面目に設計してプログラムを書かねばならないなどスクリプトの書き方では無い、何かは分からないがしかし確実に何かが間違っている(※1)

という事でもう一度クラス機能やらを全て破棄して考え直すべし.

 

※1) あくまで自分の用途および分野でのコンピュータの話だが、awkは良いものであるし、Perlは4までは良いものだ、Perl5は真面目になりすぎた感があり、RubyやPythonは判断に苦しむ(特にWindows上での用途では)、JavaScriptはそれ自体はどうでも良いものであるがJScript.NETは確実に間違っている、PHPは多分間違っていないのだろう(最近はグダグダだが)し、JavaのGUIパーツはまず間違いだろうし、VBとVB.NETの間の隔たりはその間にあった問題の斜め上を言っている気もしないでもないというトコロ(※2)

※2) まぁでもバージョンラインを分岐させて、一度ちゃんとしたオブジェクト指向・ちゃんとした(メジャー路線の)継承までサポートした言語を作っておく事は(それ自体使うかどうかはともかく)悪くないかもしれない、以前作ったのはプロトタイプベースであるし、1箇所構造に起因する問題があったので少なくとも言語及びコアライブラリ程度まで全て完成させてみるというのも、作っておけばまぁプログラマ同士の会話のネタ程度にはなるかもしれないとも思ったり.

※2') この路線で行くとそもそもエンタープライズ用途そのものが間違っているという話にもなりかねないのだが、正直そこまで言うつもりは無い、余りに真面目に取り組み過ぎているという気はするが (まぁソフト屋としての自分自身を否定するようではあるけど、ね;-)

 

2006/10/29


という事で開き直って循環参照を許容する形で内部構造を作ってみた、Mark&Sweep単体よりはリファレンスカウンタも併用する方が若干結果が良い模様につきコアは引き続きハイブリッド型とする事に、まぁ暫く触ってみて妥協できるなら採用というカンジ.

流行ものの関数プログラミングっぽくこういう事してみたり


function func1(a,b,c){
    printf("foo(%d, %d, %d)\n",a,b,c);
}

foo=binder(func1,15,2);
foo(10);
foo=rbinder(func1,15,2);
foo(10);

---------------
実行結果
foo(15, 2, 10)
foo(10, 15, 2)

当然合成結果の関数を更に合成する事も可能 ;-)

循環参照を許可した事でメソッドにオブジェクトを格納するとこんな事もできる.


class Foo{
    var val;
    function Foo(n){
        val=n;
    }
    function say(){
        print("val : ",val);
    }
}

a=new Foo(10);
b=new Foo(12);
sa=[a.say, b.say];
for(var f in sa) f();

---------------
実行結果
val : 10
val : 12

言語としてクロージャはサポートしないもののメソッドへの参照は関数と等価であり限定的なクロージャとして扱える、無論このインスタンスメソッド対象も合成対象にする事が可能、、、というかこの辺凝りだすときりが無いな(笑)

上の話があれば(クラスの方は)余り必要無い気もするが、無名関数・クラスもサポート.


a=new class{
    var val;
    function _(n){ val=n; }
    function call(){ print(val); }
}(10);
a.call();

a=function(a,b){ printf("(%d, %d)", a, b); };
a(1,2);

---------------
実行結果
10
(1, 2)

binder/rbinder(関数合成)の引数に無名関数と関数オブジェクトを渡す事で更に複雑な関係も定義可能となる.

他にもこんな具合にクラスそのものをデータとして扱う事も可能、ファクトリとかストックする時に楽かも?


class Foo{
    function Foo(){
        print("Foo created");
    }
}
a=Foo;
b=new a();

---------------
実行結果
Foo created

で、上のbinderや無名関数、更にevalでのコード埋め込みまで駆使すると動的に入力データに応じたクラス定義を返し、データに応じて動的に生成されたクラスのインスタンスを作成したりも可能になるワケです(やめなさい)

、、、でそんな機能雑用スクリプトで何に使うの?ってオチが付くワケだなorz

なお継承は他のスクリプトと同じように全てVirtual、スーパークラスの明示的呼び出し・処理の委譲はsuperにて、また派生クラスで上書きされていない値を得るにはmyのメンバがカレントクラス(より上位のクラスのみ)になるよーなそんなカンジ、、、何か複雑になってきたなぁ、本当にこれで良いのだろうか、、、 :-<

# でもどっちかというとデータ型を重視したオブジェクト指向的なプログラムよりも構造の結合を重視したこういうアプローチの方がお気に入り(笑)


2006/10/28


全て上手く行ったかと思っていたが、特定のレアケースでベースクラスだけが残り派生クラスへのチェーンが削除されるケースがある事に気付く. なかなか上手くは行かぬ模様、循環参照を許容すれば問題は解決するのだが、GCとリファレンスカウンタではパフォーマンスが異なる為、余り言語標準機能を利用した場合にも循環参照構造を許可するようにはしたくない. ただGCとリファレンスカウンタのハイブリッド型を採用した部分が無駄にコードを複雑にしてしまっている部分もあるのでどうしたものか.

やはりプロトタイプ型でのオブジェクトの方が安直なのだが、現行プロトタイプ型は余り概念として普及しているとは言い難い (とは言え殆どの方法論はプロトタイプ型でもインスタンスチェーンのような構造でも実現方法が違うだけで実現できるが(※1)) ので余り気が進まない.

うーむ :-<

※1) 方法論のみで本質的な違いは余りないと言える、余談だが最近の「オブジェクト指向」 (という(政治的もしくはSE的)用語、OODでもOOPでもない) 談義ではどうも「実」よりも「型」が優先されているように思えてならない(無論自分が愚かであり「型」に見える所により深い本質があるのやもしれぬが、残念かつ不幸な事にそれを証明・反証する「事実」にはなかなか巡り合えていない :-<

---------------

試しにリファレンスカウンタを外してMark&Sweep GCのみのタイプも作ってみて検証してみようと思う、余談だがよくCプログラマと話しているとGCをオフにできる仕様は無いのか、クリティカルな時にGCが走られたらたまらん(要は実行効率に揺らぎが発生する部分)という話があるけど、ある程度徹底してObject指向の機能を組み込んでしまうとスクリプトなどではプログラマに見えない部分の中間オブジェクトもGC対象になっていたりするので、そうやって一時的にオフにしてしまうのはかなり予測不能な可能性を孕んでおり無茶な話なのかもしれない.

そうなってくると「今の流れの」オブジェクト指向そのものが間違っているのだという話にもなり得る(笑)のだが、一方オブジェクト指向(この言葉嫌いだが)的抽象化及びデータ粒度のコントロールのアプローチは有効である為、それ以外のタイムクリティカルなソフトを組んでいないユーザー(プログラマ)にとってはそれよりもGCを取る方が有用なのだろうとなって両者はなかなか交わらない.

C++などはそういった意味では中庸なのだろう (その結果があの複雑怪奇な文法ではあるが) スクリプトなどではこういった議論が果たしてスクリプトに複雑なパラダイムは必要かといった議論にならなくも無いかもしれない (あくまで思考の記述手段としての言語について、今のLLなどと言われるスクリプトブームは単に上の話だけではなく市場競争による低価格化と開発の低期間化など市場原理や人材及び教育の決定的な不足にもかかわらず案件は増加傾向にあるなど政治的事情なども含んでしまっているので(つまりは輪の中を走りつづけるネズミ、止まったら死んでしまうのですな ;-)



2006/10/26 シャングリラその後


昨日は久しぶりに大型のプログラムの神様が降りてきた模様. という事で昨日一日でOOP関連機能が全て完成(笑) 何時もこうだと申し分無いのだが、ダメな時は変数の命名がしっくり来なくて3日間位それだけ悩み続ける(他の事に全く手がつかない)事もあるので差し引きで考えるとイマイチかも:-<

という事でこういう↓表記が出来るようになった.


class Base{
    val=55;
    function say(){
        printf("Base : %d\n",val);
    }
}

class Foo : Base{
    val=22;
    function say_foo(){
        printf("Foo : %d\n",val);
    }
    function say_foo(n){
        printf("Foo : %d & %s\n",val,n);
    }
}

a=new Foo();
a.say();
a.say_foo();
a.say_foo(10);
if(a is Foo)    print("a is Foo");


ちなみに単一継承のみサポート、プロトタイプ型では無いのでちゃんとベースクラススコープではベースクラスのメンバが参照される、最近のスクリプトではレキシカルスコープの方が多い気もするが比較的安直にダイナミックスコープ(C++とかと同じ)、よってクロージャのサポートは無し、先日書いた関数の多態定義は関数オブジェクトが複数の関数エンティティを参照できる構造とする事でサポート可能としてみた (これ以外にもデフォルト引数サポートする事でも可能だが、省略のある場合と無い場合を同時に考えねばならないので余り好きじゃない、単にめんどくさいのと引数ごとに余りかけ離れた動作を実装できないというのも理由ではある)

人によっては頭がおかしいかと思われる事もあるかもしれないが配列などはオブジェクトにしないつもり(笑) つまりは書き方によってはOOP要素を全て排除できる方向で、まぁかなり割り切った感があるけど、雑用のスクリプトレベルではクラスなど使わない方が安直に書けるワケで(いちいちnewしてopenなんてそれだけで有り得ない) 必要になった時にクラスを使えば良いという結論に行き着く.

個人的にはデータ構造は全て自分で設計する派なので、クラスを使う際は複雑なデータのマネージメントやその関係を記述する目的がメインで、別にクラスライブラリを使いたいからでは無いし、みたいなそんなカンジで(だって計算アルゴリズムの検証やっている時にいちいちMath.sin(Math.PI*x)などと書かにゃならんのは少なく見積もっても神への冒涜でしょ、みたいな) だって所詮スクリプト(雑用用途)だし、本質的に余り真面目に使うべきものでは無いし、むしろ真面目に使わないべきモノなのだという結論に至る :-P


2006/10/25 シャングリラ


シャングリラが見えてきた気がするヨ.

とゆーかね、何かオブジェクトシコウトカ、モウドウデモイイキガシテキタヨ♪ ちょっと前までオブジェクトシコウナイトシンジャウヨ見たいな気分だったのだけど、むしろそんなに考える必要無いというか、あー何かキモチヨクなってきたヨみたいなそんなカンジ.

# 別にラリってるワケでは無く、至ってまともです、むしろプログラマ的な思い入れとか全部投げ捨てしまって次の局面が見えてくるみたいな;-)

2006/10/23


取り敢えず悩んでいても仕方無いので、検証用に現状仕様のGC対応版とGC&関数namespaceの変数共有版の2種のインタプリタを作成してみた、GCはリファレンスカウンタとのハイブリッド形式で、オブジェクト生成数が増えてくると自動でGCを実行する仕様、リファレンスカウンタが効いている為殆ど速度低下は無しの模様 (クロージャまで導入してしまうとハイブリッド型での効率は望めないが)

とは言っても完成したのはコアのみで、内部構造変更に伴いライブラリ関数は作り直しが必要、その数200個程度、、、namespace共有版はCOM Objectの呼び出し機構も変更する必要がある為COMアクセスライブラリ部も部分的に作り直さねばならない :-<

、、、作ってみれば過程で解が詳細に見えてくるかと思ったがイマイチ、やはり小規模(数百行程度)の雑用プログラムでは関数と変数のネームスペースは分かれていた方が (直交性は無いものの) 安直に書ける気がする、逆にコールバックを多用する場合などはネームスペース共通である方が良い、カリー化など集約・特化まで考慮するとクロージャも必要 (※1)

余談だがGC周りの挙動のデバッグはやたら面倒X-<

※1) オブジェクト指向にしても構造化にしても (逐次実行モデルに囚われる限りは) 結局はネームスペース問題と、情報をどのように効率的に集約するかという課題を解決するかという所にかかっている気がする、その問題のドメイン規模により、より一般的な方法は逆により狭い領域では記述量を増やしてしまう(※2). 逆に簡単な問題においても常に巨大なライブラリを伴う事を前提にするならオブジェクト指向的な切り分けは必要であるし有用であると言える、言語の持つポテンシャルと限定領域における安直さのバランスは非常に難しい.

※2) 個人的に (よく他人には苦笑されるが) あるロジックを表現する上で、そのアクションがロジックの1単位となる局面では1つのアクションにつき2行以上コードを書く事は悪しき事であるだと思う、ロジック一つに対応するコードは常に1行でなければならない、2行以上のコードは現在書こうとしているアクションに対し、それ以上の詳細の把握を同時に求めてしまう為、コードを書く上での思考と実装が乖離してしまう(※3)

※3) 先日のNemerleなどLisp的なマクロに拘る理由はここにある、C++のテンプレートや演算子のオーバーロード程度の機能ではこれを実践するのは限界があり、クラス機能での記述だけでは相関を表すには不自然になってしまうケースもある (無論boostのMPLは論外、あれならまだLispの文法の方が自然に見える、それが自然に書けるという事が重要なので) 更に推し進めるにはリテラル表記や文法そのものまで変更可能である必要がある、まぁ企業における仕様書にソースの文法の記述から書かれているなどというのは想像できないので、現状のエンプラ系(とは言え近年の殆どのスクリプトなどは「ソレ」向けだ)などには不向きであり、メジャーな言語にLispのマクロ並みのメタプログラミング機能が搭載になる事は無いのかもしれないが orz(※4)

※4) とは言え自分もそういう事ができる言語ではきっちり信頼しているプログラマのコードしか触りたくないのは事実(苦笑)

 

※3') つまりお前の頭が悪いから2行以上のコードは理解できないのだろうというツッコミはアリ(苦笑、自虐っぽいけど自分の場合実際1行のコードと2行以上のコードを瞬間的に認識・記述する際には思考のラグに相違があるので仕方無い)


2006/10/20


自前のスクリプト、どうにも複雑な処理を書いているとフルセットのGCが無いのがイライラする、主に構造体での話だがロジックプロトタイプを組んでいるとどうしても(C++でのクセで)そういうデータ構造を設計してしまうのが問題、リファレンスカウンタで満足の行くレベルはせいぜい値, 文字列, 配列(ネスト無し), 組み込みオブジェクト(ハンドルのようなもの)といった所なので作り直しを検討中.

現行の仕様をGC対応にするのは左程労力では無いのだが、どうせフルGCをサポートするならクラスも入れたくなる、ただそうすると現状関数と変数でネームスペースを分けている辺りが影響する (問題の本質では無いがクラスの使用が頻繁になると分断の影響が顕在化し易くなるので一貫化させる方が文法に統一性が出る) しかし、これを変数と同一スコープにしてしまうと現状の仕様での関数の引数によるオーバーロードが出来なくなる、あるいは工夫が必要な仕様になる.

またクロージャ(あると便利なんだこれが)に対応させるかどうかによってGC部分の根本的な設計も変わってくる(クロージャと関数定義を一貫化すると必然的に循環参照の頻度が大きくなる為フルGC処理を常態化する方が妥当、またブロックスコープ(※1)のコストも高くなる)のでどーするかといった所.

クロージャもサポートさせるなら流行モノで遅延評価も導入してみると良いかもしれない、限定的な仕様であればこのようにトランスレートできる.


foo(a,lazy(expression));

これを以下のようにクロージャとして変換する.

foo(a, function(){ return expression; });

function foo(a,b){
    if(a>10)    return b;   <-ここでbが遅延評価式であった場合初めて評価を実行する.
    return a;
}

※expression内に更に遅延評価式が含まれている場合上記の必要になった時点で再帰的に評価される.

無論無限リストのような構造をサポートするなら更に熟考の余地がある(※2) しかし無限リスト及び無限リストを利用する文脈などを考慮すると全てが遅延評価であるHaskellのような言語はともかく、副作用が前提の手続き型言語では全ての式が遅延評価になっているワケではない為、部分的な遅延評価は流行モノとしてはアリでも、実際は単にバグの温床にしかならない気もする.

さてさて.

※1) ブロックスコープはダラダラとコードを書き殴る上では安直に継ぎ足し出来る要素である為、個人的には無いと辛い、無論前述のような話は使い捨てプログラムに限定しての話で、正式なプログラムをどのように書くべきかについては議論の余地があるが.

※2) 無論安易な無限リストのような構造は (思考実験としては良いものの) 果たして逐次実行モデルにおいて良いものであるかは議論の余地がある気がする、静的に結合しない状態での2次元以上のこのような構造は項の依存関係によっては現状のPCリソースを安易に消費し尽くす可能性もあり、安定したプログラムという事では必要に応じたキャッシュ構造のようなものを自前で実装する方が妥当な気もしなくもない.

---------------

先日のPHPの演算子の評価順序が変という話、元ゲーム屋さんの人に話したら、そもそも組み込みなどではメーカー製コンパイラがどマイナーだったりするケースもあるので3項演算子なんかは評価順序がヤバい匂いがする個所なので使わないんだそーな、、、PCプログラマからは想像もつかない環境だ.

まぁgccベースならまだ良いけど、確かに国内メーカー製で限定的な市場にしか出荷されていないC++コンパイラなんて正直恐ろしい事この上ないのだけど、と言ったらそれどころかCコンパイラでも安定しないものもあるとの事、やっぱ同じプログラマという肩書きでも業種によって常識が違うのだなぁ、など.

 

2006/10/18 駄ネタ


殆どまともに触ってなかった(仕事でエンプラ屋やエンドユーザー向けにCOMを作る時の検証程度)のだけど、VB6のオブジェクト管理って参照カウンタだったらしい、、、(COMオブジェクトだけじゃないって話だよね(^^;;

.NETのメモリ管理について

>Microsoft がガベージコレクションへの切り替えに踏み切ったのは、Visual Basic の参照カウントアルゴリズムが、
> 子オブジェクトから親への参照を持つという循環オブジェクト参照をきちんと処理できなかったためです。

ってゆーか怖っ(大汗) 一応世のビジネスアプリってこれで作られているものまだ結構ある筈なのだよねぇ(^^;; まぁオブジェクトや構造体の概念が弱くオブジェクトを作る事が殆ど無い言語でかつプレースホルダになる構造体や配列が全て実体コピーであるなら余り問題無いかもしれないけど、プロセスのライフサイクルが長い言語でこれはちと辛いかも.

---------------

PHPの3項演算子って変らしい

PHPの三項演算子って変じゃね?(個人ブログ、無断リンクですm(_ _)m)

、、、こういうのって初期バージョンのパーサ書いた時のバグがそのまま紛れ込んで発覚した時には過去の互換性を気にして直せない羽目になっているか、あるいは作成者の明確な意図 (3項演算子は優先度が(慣れないと)分かり辛い(人もいる)ので明確に括弧でくくるコーディングを強制している)というののどちらかだと思うのだけど、どーなんだろう.

余談だけどスクリプト系で言えばPHPのローカル変数規則 (ローカルスコープが標準でグローバル変数を使用する場合は明示的に参照指定する)ってプログラム規模が小さい場合には良いのだけど、プログラム規模が大きくなると余り良くない気もする (あくまで手続き型メインでオブジェクト指向プログラミング機能をOptional的に使うのであれば)

個人的にはPythonの規則 (参照のみ許可、代入は明示宣言が無ければローカルで初期化される)って辺りが理想と現実の妥協ラインっぽくて好み、破壊的呼び出しなども考慮すると決して一貫性があるワケでは無いのだけど、実際書いている時の直感には即していると思うし、余り混乱はしない.

これがRubyになるとグローバル変数は先頭に$記号が付加したものでローカル変数と明確に区別される、論理的一貫性はこれが(実用面も考慮すると)優れているものの、個人的にはコーディング時の名前規則を強制されるようで余り好きでは無い. ただ他人が見た時の可読性(※1)という事では明確に区別できる辺り良いのかも.

この辺微細な部分ではあるものの各言語の性格や作者の考慮したであろう命題が見えてきて面白い気がする.

※1) Basic言語のend for,while etcとC系の{} (あるいはPascal系とかのbegin〜end)の議論なんかも似ている、極めて冗長な構文だと思うけど、どちらが何も情報が無い状態の他人が見た時にプログラムの構造が明確になるかという所は考慮の余地がある、個人的には書いていて気持ち良いのは断然後者 (でもbegin〜end表記は嫌い)なのだけど、不特定多数のメンテナンスやバベルの塔のごとく積み上げられたコード(別に企業のヘタレコードに限らず、メンテナンスを経て#if〜#endifなどの山になったオープンソース系のコードも含む)を扱う際にどちらが良いのかは議論の分かれる所だと思う(まぁその前にそんな分かり難いループのネストは書くなというツッコミもあるのは事実だけど ;-)

※2) 余談だけどPHPに関しては殆どの機能がオブジェクトライブラリでは無く(醜悪な位大量の)プリフィクスの付いた関数として提供されている辺りも興味深い所、はっきり言ってスコープの損益分岐点に到達している気もするのだけど、それなりに人気があったりするワケで、どういったモノが人間(あるいはエントリユーザー|プログラマ)の脳に適しているのかってのはオブジェクトライブラリの学習曲線や粒度、ライブラリ間の結合を疎結合で設計するか密結合で設計するかなどの考えるネタとして興味深いと思う.

まぁ、、、C++だとそんなに複雑なオブジェクト階層にするとリソース管理にムチャがあるので、疎結合で作るしか無い気もしますが(苦笑)

---------------

日記補足

先日↓のような内容を書いたのだけど

>何と言うか世間のスクリプトブームって 影にC/C++のリソース管理に対する怨念めいたものを感じるような気もしてみたり

これの背景に昔会社勤めをしていた時にクライアントのおじさんが障害に対して「もしかしてメモリリークですか?」などと話していたという話があり、まぁ相手はそういう(プログラミングに関わる)業種では無い為、よくまぁ「メモリリーク」なんて単語を知っているなぁと思ってみたり、まぁそういう話が1件では無く数件耳にした事もあり「メモリリーク」という単語がコンピュータ業界でクライアントに対しどのようなコンテキストで使われてきた伝統があるのかなぁなどと考えてしまった背景がある。

何か普通(って言い方もアレだけど)の人が「コンピュータウィルス」と言っているのと同じで、形の無いイメージが一人歩きしているようなそんな印象. まぁそれもまた含めて文化なのだけど、そういった所のイメージが「メモリリーク」あるいは「GC搭載言語です」といったイメージと合わせてこの流れを構築しているのじゃないかなぁとかそういうイメージ (無論それだけという話では無くあくまである一側面であるワケだけど、「メモリリーク」への形骸化し記号化した神経質さのようなものなんかも会社時代の「仕事でだけやってる」上司や先輩(って言い方もアレだけど、仕事では単に同僚という認識しか無いので))なんか見てて感じてみたり.)

---------------

余裕をみてHaskellなど勉強中、最初は???といったカンジだったものの大分イメージが掴めてきた、Lisp以来久しぶりにプログラミングの概念から違うものなんで結構新鮮、やっぱこういうのって面白いなー、、、役に立つかはともかく(笑)

 

2006/10/08 .NET集中講義(笑)


この土日を利用して久しぶりに.NET Framework 2.0を触ってみる事に
、、、というかGDI+ってそのままなのね(^^;;

悪い予感がしながらも取り敢えず C#でBG描画無しでスレッド起こして24bit Bitmap (not DIBね、GDI+は内部で全部ソフト処理になっているみたいだし、メモリの構成も微妙に違うので) 640x480の画像を4枚転送してみた所、CPU使用率が30〜40%程度(プロセス自体の占有は5%程度だがSystem占有が30%程度(※1)) 同様の処理をC++&GDI(24bit DIB)で行った所では使用率はほぼ1〜2%程度(System占有なし) タスク切り替えなどでBusyになった場合でも3〜5%程度が上限(Pen4 2.8GHz使用)

また以前C++でGDIとGDI+の描画性能を比較した所アルファ合成無しで2〜3倍程度GDI+が遅かった(プロセス占有率は未測定、単純に転送速度ベース) アルファ付き+ガンマ補正有で行うと50倍程度遅くなるのでこれは描画というよりは合成処理専用として、ガンマ無しアルファ付き合成も (これはAlphaBlend()と合成式が違うので自前の適当なアルファ合成ルーチンと比較(※2))半分程度のパフォーマンスしか出てなかった.

※1) Nativeアプリの場合と比較するとこの出方は少々奇妙な気もするが、ちなみに枚数を増やした(2倍描画)所ではSystem占有率は30%止まりでそれ以降は本体プロセスの占有時間として+30%程度上乗せされている. なおGDIの場合も枚数を増やした場合(VRAM転送なども想定されるので全て異なるDIB扱い)とした所ではやはり数(1〜3)%程度でSystem等の占有は無し、うーむ:-<

※2) かなり安直に書いたルーチンの筈なのだが、というか個人的には所謂「職人タイプ」では無いので、よくあるプログラマネタのカリカリにチューニングって苦手(というか面倒なので露骨に嫌い(ぉ)な方なのだけど、理論通りに実装してそのまま動きゃいーじゃんみたいな、まぁどうしようも無い部分はチューニングするけど、、、てなワケで結構プログラマ(というかエンジニア)には向いてないかもなーなどと自分 では思っていたり(^^;;

---------------

、、、正直描画が全てであるとは言わないし、よくあるベンチの結果など純粋なコードのトランスレーションはコンパイラ型言語と同程度なのかもしれないが (少なくともクライアントサイドのある規模以上のアプリを作成する場合には) このようなベンチマークは全く意味が無い(これはJavaのベンチマークなどでも同様).

一般にある規模以上のアプリの実行速度は均一な速度で実行されるのでは無く、そのパフォーマンスは律速段階となる全体のほぼ数%の部分に左右され、また描画周りなどは実際の速度以上にパフォーマンスの「印象」を与える上で重要な要素になる事を考えると、この描画の遅さはダイアログベースなどのボタンが並んだ安直なアプリでは問題無いが、ある規模以上のインタラクティブな操作を伴うアプリ作成では致命的とも言える.

まぁ実際は最近のビデオカードはBlit時のsrc<->dst間の簡単な色変換やAlphaBlend()などの合成式はそのままハードウェアでサポートしていたりするので、GDIの方は部分的にアクセラレーションが効いている可能性は高いのだが、これにした所でNativeで書いたアプリが暗黙のアクセラレーションを利用できるかもしれないのに対し .NET Frameworkで書いたものがNGであれば(ユーザーにとってアプリが何で書かれているかは全く関係無いので) その部分のレスポンスがダイレクトに評価に繋がってくる可能性は高い.

うーむ、相変わらず微妙な完成度:-<>.NET
まぁVistaで描画周りがDirectXになればその部分も(内部的に実装を分けるなら)改善されるかもしれないが、少なくとも今のままじゃ完全にダメダメだろ、、、sigh


---------------

.NET Frameworkってとっかかりは簡単だし、設計もMFCに比べたら数千倍マシ(あれはWindow抽象化以上のゴテゴテした機能まで大量に実装している割にダイアログベース以上のアプリを書こうとすると逆にWin32より不便になるという露骨に酷いシロモノ) なのだけど、ある規模以上になると結局Win32とコードの記述量変わらない のだよねぇ、無論下準備としてC++はそういうクラスを書く事が前提で、Webのサンプルコード そのままコピペしたみたいにどこまでもフラットなAPI呼び出し を書く事を考えると.NET Frameworkに圧倒的なアドバンテージがあるが、そもそもそんなコードを書く輩はプログラマ向いてないだろ、みたいな(笑)

無論リソース管理が厳密でなくとも良い部分で所有権を曖昧にしたまま様々なユニットにオブジェクト放り投げて処理単位を構築できる部分は メリットではあるけど、これにした所で方法論さえ確立してしまえば (この部分の自由度は確かに言語の自由度に左右されるが) C++であっても左程問題無い気もする(無論それが出来る事で更なる設計論を模索できる事は確かだけど;-)

それ以外でのフレームワーク自体のパフォーマンス及びメモリ効率の悪さ(まぁこれにしてもNativeですら それに抵触し得るアプリを書いている事が前提だけど)と必要に迫られた時点でのNativeとの親和性の悪さ を考えると、、、

オブジェクト指向ライブラリも確かに綺麗だけど、いちいちsprintf()をString.Format(), Sleep()をThread.Sleep() などと書く事を全般に渡って強制される事を考えるとどちらが効率が良いのやら(だってタイプ量が多いと指が疲れるじゃん(マテコラ)ましてやShift押下すると余計疲れるし(ヲイヲイ)みたいな(えー

何か大風呂敷を広げている割にはVBの代替品程度の価値しか見出せないよ>.NET Framework...orz
まだ(コンパイラの最適化は悪い (純粋ロジック部分でVC++の1.5〜2.5倍程度遅い、アプリにすると別の部分の律速段階の影響で余り変わらない事も多いけど) のけど) Nativeとの親和性などを考えるとC++Builderのがマシじゃん、みたいな. これもまた現状グダグダだったり最近はバグだらけという話も聞くのだけど、簡単なアプリでっち上げるなら便利だし、潰れる(ヲイ)にしても64bit版吐ける作ってからにしてくれないかしらん(コラコラ)

JScript.NETとかもC#と基本的に記述量変わらないし、列挙体や構造体などimportで名前 を書いてもフルネームでしかアクセス許可してくれないっぽいので、下手すりゃC#よりも記述量 多くなるし、というかjsc.exeは.NET1.1の頃から殆ど放置状態っぽい気もする(笑)
今となってはこの言語の唯一のメリットはクロージャが使える事位かも(そしてそれ以上のデメリットがある(涙)) C#2.0の無名関数は個人的にまだ面倒なのだけどsigh

---------------

先日書いたNemerle(ネマールと読むらしい)も動作しました、これについては後日書く予定.

色々.NETについてボロクソに書いている気もするのだけど、別段アンチ.NETというワケでは無く、むしろ発表当初はかなり期待していたし、今でも何かのきっかけで大化けしてくれないかなぁなんて思ってたりするんですよね. かつてC++を揶揄する話として 「WindowsのプログラムがC++とVBに分かれた時、一握りの頭の良いプログラマやプライドの高いプログラマはC++を選び、残りの大多数はVBを選んだ、そしてその後C++プログラマが書いたソフトよりVBプログラマが書いたソフトの方がよっぽどバグが少なかったのだ」 という話があり(無論現実に即した時この話は必ずしも真では無いが、ある側面については的確に表している) だったらやっぱ楽して書きたいじゃーん、みたいな. 無論その為には2つの言語が (言語としてでは無くプラットフォームを利用する上で) 同じポテンシャルを持っている事が前提になるワケですが.

特に自分のメイン分野であるクライアントサイドである程度以上複雑なアプリとなると現状C/C++以外に選択の余地など無いワケで、もう少し多様性が欲しいなぁ、と.(ちなみにDは言語云々とか以前にそれを取り巻く事情がNGなのでやっぱ趣味以外には使えないカンジ(悲))


2006/10/06


ちなみに先日書いたスクリプト言語とは別に簡易matlabのような行列型の言語も色々いじっている所(今年の1月にカメラマッチを計算していたヤツ) 自前のスクリプトコアを刷新したのを機にコアを初期の電卓言語のコアから本格的な言語のコアに移行、今まで気になっていた複素数の対応なども実装してみた.

んでBASICライクなグラフィック画面をデータプロットや、アルゴリズム検証時の視覚化用に実装していたのだが、どうにもそぐわない気がしてちょっといじっている所. 現状ではこんな↓カンジ

単なるBitmapから描画コマンドを内部で全部リスト化したベクトル形式に変更、表示時に描画リストを再生する形になっているのでスクリプトで描画した後、画面をドラッグすればさまざまな角度からチェック可能なようにしてみる、2Dも任意倍率で移動・拡縮が可能なようになっている(式まではデータ化していないのであくまでlineを描画した時の分解度でしか表示しないし、浮動小数点の誤差領域まで拡大するとアレですが)

用途は自分用のアルゴリズムの検証用といった所、3Dのプログラムなんぞ書いていると立てた数式にミスがあったり行列演算などでミスったりで結構検証が面倒で (数値だけ出てきても2Dはイメージし易いけど3Dはイメージを掴み難い) 実際に動かすとオブジェクトが明後日の方向に飛んでしまったりするので、取り合えずその開発のアルゴリズム検証の時間を短縮する為のもの. RenderManSLなどでも思ったが、こういう小規模特化型言語でのプロトタイプは結構開発時に便利(汎用言語だとどうしても面倒な部分がある)だったりするので;-)

まぁ行列計算全体からすると3D表示も所詮3変数だけの写像なんでアレなのだが、まぁ自分的には使うかなーといったカンジ. こちらはスクリプトとは言っても開発環境というよりは特定用途の為のアプリケーションといった側面が強い為、言語構造などもできるだけ安直で覚える事が無いよう設計してみる.

---------------

まぁmatlabやMathematicaでも良いのだけど、それ程ガチガチの数学用途では無いし、むしろプログラマ向けのアルゴリズム検証用電卓的なカンジなので、計算規則などがもっとユルく(scriptライク)てシンプルなものが欲しかったという所. 行列関係も一通りのライブラリ(行列式、逆行列、ランク、lu分解等)は複素数まで含め実装したものの目下の悩みはまだ固有ベクトルの計算ルーチンが無い事、こればっかはかなり複雑な処理になるし、精度まで考えるとLAPACKとかから引張ってくる方が妥当なのかなぁsigh.

# こちらはどちらかというと言語というよりは電卓なのだけど、コンピュータを現実の問題に対する「計算機」と捉えるならこういう路線もアリではないかと思う、無論言語が全てでは無いしExcelなど (というかVisiCalcから始まるスプレッドシートという概念) は過去にユーザーがBASICなどで計算してきた内容をより一般化したという意味では非常に偉大(※1)だと思うが、反面このインターフェイスでは不自由な計算があるのも確かで、「計算機」あるいは「思考を検証する為の道具」としてのコンピュータの可能性を色々思い巡らせるのもまた一興. まぁ実社会でそんな複雑な計算無いよってツッコミを入れてしまうとそこまでではあるのだが、ただ道具が思考を規定するなら無駄な作業の一切を道具にやらせる事で、もっと人間は創造的にもなれるのではないかと(また大きく出たな)

# というかね、もう少しすると仕事で行列計算で阿波踊りする羽目になりそうなんで、それ用の準備も兼ねてたりするのですな(ってそっちが本音(笑)

※1) まぁこれも昔は「表計算言語」と言ったりしたし、こういう路線ではVB(6まで)も言語としてはダメダメだけどアプリケーションとしては秀逸だと思う、少なくともそれが想定している範囲で扱うについては、という話でVBで無理矢理Win32叩きまくるのはアホかという話でしか無いのだけど、そういった意味では出た当初のHSPもオーサリングツール (not プログラム言語) という局面ではかなりいい線行ってたと思う、その後これをまともなプログラム環境としてあれもしたいこれもしたいという事でゴテゴテ付けていった路線はそも論外だと思うけど (過去のBASIC狂想曲を見ているみたいで何とも何とも、それを取り巻くユーザーの気持ちは分からいでもないけど、技術のトレードオフポイントの見極めは重要ではないかなぁ、と)

まぁとは言え最も偉大なのは紙と鉛筆と人間の想像力だって気はしますが(笑)

 

2006/10/05 猫文学、あるいはロバの耳


巡回してて見つけたNemerleなる言語が面白そう、インストールに.NET Framework 2.0が必要という事で入れていないがC系の文法(見た目だけならかなりC#,JScript.NET(2.0))に近いカンジの言語(※1) まぁオブジェクト指向とかはどうでも良い(ヲイ)のだけど、特筆すべきはどうもLISPと同等(らしい)マクロ機能があるという事らしい.

実際サイトの解説を見ても単なるテンプレート埋め込みや部分展開だけで無く構文もちゃんと拡張できるシロモノらしい(while文の実装サンプルなど)後は入力データとMacroで使用するシンボルが相互可変ならかなり遊べるのだけど(笑)

もう少しメジャーになってマニュアルの翻訳とかオンラインで日本語の情報出てきてくれると良いのだけど、英文読みながら言語のクセを掴むのって結構ハードなので、まぁちと暫くアンテナ張ってみようと思う.

※1) 実際はC言語風の文法の殆どは前述のマクロで記述されているらしいのだが(笑)

---------------

まぁ、とは言っても所詮プログラミング言語なんて「自分の欲しい動作をするソフトを作る」手段でしか無いので、マイナー言語 (特に汎用言語はアプリケーションというより環境という特性が強い) いじくるってのは所詮プログラマのマスターベーションでしか無いのだけど、絵に例えるなら画材についてアレコレグダグダ言うのと同じ話、そんな拘りは当人だけの問題で、実際はそれに伴う方法論が確率できりゃ(絵を完成させる手法が確立すりゃ)極端な話何でも良いワケですが:-P

それでもこういう言語遊びは好きなんですよね、某氏とかには馬鹿にされるけど(笑)

目下の悩みは身近な周りの真っ当なプログラマ(笑)にはOOPLどころかCプログラマ(not C++)が殆どという所、ので、こういう議論で参考意見聞いても全く参考にならない でも言語が単なる目的のための手段と捉えるならシンプルで覚える事が少ない言語が一番で (記述やメンテのトレードオフバランスはあれど) それに伴う方法論など言語に関係無い部分の知識を充実させるという方が重要というのも一理あるかもしれない、前の会社でも(C++だけど)の巨大な言語仕様に踊らされてまともにモノを作れないエンジニアも沢山いたし、、、(^^;;

毒吐き的に言うと、まぁ新しいパラダイムがあれば何か凄いプログラムが書けるかもしれないってのはそも幻想で、出来ないヤツは出来ないし(ヲレヲレ(爆死))出来る人は出来るって事かもしれない、ハリウッドのカンフー映画みたいにワケわからない修行をやったら何時の間にか強くなってたなんて話は弱者のカタルシスはあれど所詮はファンタジー、全ては現状から繋がっているって所なのかもという気もしないでもなかったり(苦笑)

でもってオチは、そもそもそんな程度の事をコストと言っている時点でお前(自分)がダメなんだというオチになるか、、、物事の飲み込み悪いんだよねorz

---------------

ちと思う所があって今更OpenGL赤本購入、末尾の用語解説の所で (うろ覚えだけど)

C 「神が与えたもうたプログラム言語」
C++ 「異端の神が与えたもうたオブジェクト指向のプログラム言語」

に吹いた、、、まぁねぇ(笑)

2006/10/04


気が付けばもう10月、半年程更新していなかった事になる.

別段忙しいとかそういう訳では無いのだが (時間が無いなどという台詞は言い訳でしか無いし:-P) 4月に仕事を変わって(?)からというもの 立て続けに頭の痛い話が噴出し事態がかなり人的にシビアな話であった為 メンタル的及び政治判断としてあまり書く気分になれなかったという話もある.

まぁ余り深刻に考えてもアレなので、気分転換という所.

---------------

とは言えここ暫くはLWは触っていない(※1) というのも6月頃から書いているプログラム を引きずっている為. 元々のきっかけはたまに使うPerlの文法が気に入らない(変数に$が付く のがムカつくとかその程度)というもので、気に食わないので新しくテキストフィルタ用 の言語を作り始めたのがそもそもの始まり.

用途自体はPythonでもRubyでも良い話なのだが、普段C/C++系を使っているので、たかだか 日々の雑用程度のものを書くのに書式が異なるのが気に食わなかった、またawkは言語 として不十分であるしJavaScript(WSH等)はそういう目的の機能は充実していない.

実装はawkの文法でまともなスコープと構造体、バイナリの取り扱いに複数日本語コードのサポート 程度の機能を持ったPerl4的なもの、クラスはサポートしない、メモリ管理はリファレンスカウンタベース(まぁ使い捨て プログラム用なので稀に循環参照が発生してもプログラムの寿命的に問題なし)という所.

言語自体は3週間程度で完成したのだが、何の気の迷いかそこにBASICライクなグラフィック機能 を付けた辺りから迷走が始まる.

気が付けばTextRAMや昔ながらのフレームバッファ式で重ね合わせをサポートするVRAMもどきを 作っていたり、スプライトドライバやMCIのコントロール、MMLシーケンサやJoyStickの入力 などを作って(機能の絞込みがイマイチな部分もありプロトタイプ的に)今に至る.

まぁその過程でライブラリが充実してくるワケで、気付けばC++用のスクリプト系やゲーム系 のライブラリが手元に大量に残る事になったワケで、所詮スクリプトなんてプロトタイプ 目的でしか使わないのだから、だったらC++で書けばいーじゃん的なオチが既についている のは事実(苦笑) (※2)

そしてまたこれを書いている時間を合計すると(少なくとも今の方面では)自分にとって10年分位の Perlの記述時間程度は既に費やしているのも事実、、、ってダメじゃん(笑)


※1) まぁもう少ししたら仕事で3Dソフト使う予定があるので話は変わってくるかも、というかまだLW9買ってないけど(笑)

※2) 個人的にはコンパイルが面倒なのとファイルが複数できる以外は別段C++で困ってない、 特化型言語に比べ記述量が多いのは問題だが、スクリプトでも汎用言語では似たような記述量 になってしまうし、メモリ・リソース管理は定型化しているので悩んだ事無いし:-P
簡易業務にC++とかで効率が悪いのは事実だけど、何と言うか世間のスクリプトブームって 影にC/C++のリソース管理に対する怨念めいたものを感じるような気もしてみたり、 ま、言語的にC++では苦しい概念があるのも事実だけど(Lispのマクロ的なものとかクロージャとかリフレクションとか)


---------------

まぁそんなこんなで余り視野狭窄に陥っても仕方無いのでぼちぼち気分転換を織り交ぜてやって行こうと思うておりますというトコロ;-)

最後に、、、カプコンのGodHand購入、仕事などの合間に息抜きでやっているのだけど、連打のし過ぎで腕(not指)が痛い、正直息抜きになってない、いや馬鹿っぽくて面白いんだけどさ(苦笑)

 



過去の雑記
2006年 4月〜9月の雑記はありません.
2006年 3月
2006年 2月
2006年 1月
2005年 12月
2005年 11月
2005年 10月
2005年 9月
2005年 8月
2005年 7月
2005年 6月
2005年 5月
2005年 4月
2005年 3月
2005年 2月
2005年 1月
2004年度


メールアドレス収集ロボット対策の為メールアドレスはHP上に記載しておりません、
ソフト内のドキュメントには記載しておりますので、御用の方はそちらまでお願いします.
since 2003/10/04, Y.Ume/Tabo