著作一覧 |
Ruby-1.9.1-p0がリリースされました。関係各位、お疲れ様でした。
例によって、MSWin32版のMSIインストールパッケージを作成したのでご利用ください。
なお、リリース版ということなので、これまでパッケージに含めていなかったri用ページも含めました。結果としてパッケージは14MBというサイズとなったため、スタティックリンクライブラリは同梱していません(手持ちの16MB USBメモリーに入らなくなる)。したがって、同梱する気もありません。必要な方は自分でビルドしてください。
前回に引き続き、swin/vruby+おれさまパッチと、chm形式るりまプロジェクト成果物を同梱しています。こちらについても関係各位に感謝します。
ダウンロードは、パッケージのページからどうぞ。
なんか、Cっておもしろいなぁとつくづく思うできごとがあったのだが、なぜかというとプリプロセッサマクロがあるからだ。
つまり、マクロはおもしろい、ということなのだろう。
で、ふと気付くが、外部DSLって、つまりはマクロだな。
CSSも、マクロと言えなくないな。
ということは、XSLTもマクロだな。
と、考えると、別にマクロはおもしろいわけではない。ということは、Cがおもしろいのだろう。
やっと簡単なやつが動いた。
何が問題だったか?
組み込みRubyではruby_script(const char*)を呼び出して$0を設定できる。別に設定しなくとも良いはず。
で、GRScriptは$0が存在するので当然設定したのだが、RScriptは何もしていなかった。
そこで例外が起きる。
このとき、vmがスタックトレースを取ろうと動き出す。ここがインライン展開されていることに気づかず、コードとソースが一致しなくて最初、戸惑ったが、結局のところ
ary = vm_backtrace_each(th, RUBY_VM_NEXT_CONTROL_FRAME(cfp), top_of_cfp, RSTRING_PTR(th->vm->progname), 0, ary);
で、th->vm_prognameがQnil(ではなくNULL)なのでそこで、PTRを取ろうとしてSEGVしていた。
で、ruby_script関数を忘れていたので、次のパッチを作って、あわやruby-devへ投稿かというときに、ruby_script関数を思い出して決着。
ary = vm_backtrace_each(th, RUBY_VM_NEXT_CONTROL_FRAME(cfp), top_of_cfp, StringValuePtr(th->vm->progname), 0, ary);(でも、他でも組み込みRubyを使っていれば、ありそうな問題ではあるので、書いておいた)
RubyizeでRubyのオブジェクトをラップしているところで2個所。
1つは、String#eachが無くなった件。NewENUM呼ばれたら最初にrespond_to(:each)して、次にrespond_to(:each_line)するように変更。
2つめは、methodsがSymbolを返すようになった点。methodsの戻り値がSymbolだったらrb_sym_to_sを呼ぶように修正。
rb_load_protectでロードしたファイルの中でrequireを呼ぶと、さらにそこから呼び出したファイルのエンコーディングがおかしくなった。
具体的には、ロードしたファイルの中でrequire 'unit/test'している中から呼ばれた'mini/test'の中でFile.expand_path __FILE__
している箇所で、cp932からus-asciiのエンコーディング違いで例外となる。
file_exapnd_pathの最後に実行しているrb_enc_checkに引っかかる。
とりあえずruby.cの真似をして
VALUE enc = rb_enc_from_encoding(rb_locale_encoding()); rb_enc_set_default_external(enc); rb_enc_set_default_internal(enc);をruby_initの直後に呼ぶようにして回避した。
Ruby 1.9.1で組み込みRubyをプログラミングするには、1.8のときより必須事項が増えているので、それについて示してみます。ただしWin32用です。
以下が標準的なコード(C++用にしてみたり)となると思います。(20090206参照)
#define WIN32_LEAN_AND_MEAN #include <windows.h> #include "ruby.h" extern "C" { #include "ruby/encoding.h" } static char* test_src[] = { "begin\n", " require 'test/unit'\n", "rescue => e\n", " puts \"#{e}\"\n", "end\n", "puts RUBY_VERSION\n", "gets()\n", "\n"}; int main(int argc, char* argv[]) { #if defined(USE_ARGS) ruby_sysinit(argc, argv); #else static int dummyargc(0); static char** vec; ruby_sysinit(&dummyargc, &vec); #endif ruby_init(); // GC用にスタックポインタを設定、vmの起動 #if defined(USE_ARGS) ruby_options(argc, argv); #else // ruby_options(process_options)の処理を肩代わり ruby_script("Embeded Ruby"); // BT採取で死ぬので必須 VALUE enc = rb_enc_from_encoding(rb_locale_encoding()); rb_enc_set_default_external(enc); // コメント欄参照。 rb_enc_set_default_internal(enc); // ruby_init_loadpath(); // 常識的に必須(ruby/ver/arch,site_ruby,site_ruby/ver,site_ruby/ver/archなどが設定される) #endif rb_require("win32ole"); // 拡張ライブラリのロード char szTemp[_MAX_PATH]; GetTempPathA(_MAX_PATH, szTemp); char szTempFile[_MAX_PATH]; GetTempFileNameA(szTemp, "rb1", 0, szTempFile); HANDLE h = CreateFile(szTempFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); for (int i = 0; i < sizeof(test_src)/sizeof(char*); i++) { DWORD dw; WriteFile(h, test_src[i], strlen(test_src[i]), &dw, NULL); } CloseHandle(h); int state = 0; for (i = 0; szTempFile[i]; i++) { if (szTempFile[i] == '\\') szTempFile[i] = '/'; } rb_load_protect(rb_str_new2(szTempFile), 0, &state); if (state) { printf("script error %d\n", state); } ruby_finalize(); return 0; }
問題点:win32では、fcloseがrb_w32_fcloseに置き換えられ、しかもそこでクラッシュする(fflushでINVALID FILE*になる)。……でも、win32/win32.cを読む限り、それはおかしいな。後で調べてみることにする。
デブサミ2009をlivedoorReaderで読んでたら、「愚地さんだぜ? みんな聞かなくていいの?」なんて書いてあるじゃん。
なぜ、デブサミに伝説の虎殺しが、ってびっくりしたけど、あの人は一度、勇次郎に息の根を止められているから、そりゃデブサミくらいには出てくるだろう、にしても、何のネタか? と不思議に思った。もちろん、単なる見間違いだが、遠視になると良くあることでもある。
子供が買ってくれろと泣く子なので、買ってやろうとしたら、DSは廃版、Wiiは発売前、いったいなにが欲しいのかと聞くと、聞くまでもなかったと後で気づくが両方とか言い出し、まあ、それもありかな、と両方注文。
(売られる前からなぜ評があるのか?)
(1円じゃないとこみると、そこそこ需要があるんだろうな、というか需要は同じ屋根の下にあったわけだし)
エンコーディングの問題はrb_enc_find_index("encdb");
の呼び出しで解決。
rb_enc_find_indexは引数で指定されたエンコーディングが登録されていなければ、encの下から指定されたエンコーディングをロードする。
encdbは、encdb.c(encdb.h)で定義されたエンコード名とエイリアスを登録する拡張ライブラリなので、これによってCP932=Windows-31Jも登録される。したがって、Win32OLEはダミーのCP932を作らずに、encdbによって登録されたCP932=Windows-31Jを使うようになる。ということらしい。
したがって、ruby_optionsを呼ばずにRuby-1.9.1を組み込む場合、エンコーディングの初期登録として、rb_enc_find_index("encdb")
を呼び出す必要がある。
#define WIN32_LEAN_AND_MEAN #include#include "ruby.h" extern "C" { #include "ruby/encoding.h" } static char* test_src[] = { "begin\n", " require 'test/unit'\n", "rescue => e\n", " puts \"#{e}\"\n", "end\n", "puts RUBY_VERSION\n", "gets()\n", "\n"}; int main(int argc, char* argv[]) { #if defined(USE_ARGS) ruby_sysinit(argc, argv); #else static int dummyargc(0); static char** vec; ruby_sysinit(&dummyargc, &vec); #endif ruby_init(); // GC用にスタックポインタを設定、vmの起動 #if defined(USE_ARGS) ruby_options(argc, argv); #else // ruby_options(process_options)の処理を肩代わり ruby_script("Embeded Ruby"); // BT採取で死ぬので必須 ruby_init_loadpath(); // 常識的に必須(ruby/ver/arch,site_ruby,site_ruby/ver,site_ruby/ver/archなどが設定される) rb_enc_find_index("encdb"); #endif rb_require("win32ole"); // 拡張ライブラリのロード char szTemp[_MAX_PATH]; GetTempPathA(_MAX_PATH, szTemp); char szTempFile[_MAX_PATH]; GetTempFileNameA(szTemp, "rb1", 0, szTempFile); HANDLE h = CreateFile(szTempFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); for (int i = 0; i < sizeof(test_src)/sizeof(char*); i++) { DWORD dw; WriteFile(h, test_src[i], strlen(test_src[i]), &dw, NULL); } CloseHandle(h); int state = 0; for (i = 0; szTempFile[i]; i++) { if (szTempFile[i] == '\\') szTempFile[i] = '/'; } rb_load_protect(rb_str_new2(szTempFile), 0, &state); if (state) { printf("script error %d\n", state); } ruby_finalize(); return 0; }
「stack もきちんと説明してない……」は、「だといやだよね」というような憶測を喋ったので、実際にどうかは読んでいないのでわからないです。誤解を招く発言をしてごめんなさい。
とても悲しくなる。というか、なんでこれ読んでんだろう? とはてなになりながら、それでもおもしろいフリージア。
なんとなくオートバイとマフラーが喚起する風景に郷愁を覚えて、まったくそれが何か知らずに買い、あまりのおもしろさにぶったまげた。っていうか、おもしろい。
最初は、びんぼーマンガだと思いながら読んでいると、意表をつく展開となり、気づくと、あたかもエメリッヒもかくやというスペクタクルとなってびっくり仰天。
もしかして知られざる大傑作かと読み進めると、どんどん失速し、話の落ち着き先も、なんか若松孝二の昔の作品を観ている気分になってくる、だめな人たちの西口騒乱のようになってくる。
筆者インタビューが巻末にあって、ああああああ、そうかそうか、そういうことか、おれより1つ年上というか同世代人があの頃に書いた作品なのか、とえらく納得する。
まあそれはそれとして、アジを始める前までのおもしろさは天下一品、残された地元の少年団のエピソードも無茶苦茶おもしろいし、全体としては、失敗した大傑作ではあった。
作家と読者の両方が、自意識が肥大した頭のおかしなやつとお互いを認識してしまうタイプのマンガをおもしろいと感じるおれは、まあ、そのての人なのだろうと、うんざりするが、しょうがない。
それはそれとしてリボーンの最新刊を後で買おう。
最近、明るさが減ってきたなと感じてた電球が切れた。電球が切れるというのはどういうことなのか、あらためて不思議になる。
ロメールを観に京橋のテアトル銀座。
17世紀の文人が5世紀のゴロワはこんなもんだろうと適当に想像して描いた牧人たちの世界という無茶苦茶な話を、ロメールがいい加減にロケして作った映画。ペルセボーほどいい加減ではなく、ちゃんとロケハンしたらしい。で、最初に、5世紀当時の面影を残す風景は失われてしまっていたので、原作が指定しているなんとか地方はあきらめて別のところで撮ったとかもっともらしいクレジットが入る。
で、主役のセラドンが愚直な男で、そのせいで川に身を投げて、ニンフと呼ばれる神女達の館の主(で、それがニンフォの語源となるのかなぁ)に拾われて、しかし脱出し、ドルイド僧とその姪かな(大活躍)のはからいで神殿建築(といっても、日本の竪穴住居をもっとラフにしたようなものなのだが)を行ってとか、物語は進む。
字幕は、「おお、美しき羊飼いよ」のような擬古調を交えるし、しゃべっている言葉もそんな感じのような、適当に現代語にしているような、役者は明らかに不自然なシーンではへらへら笑いながら、いつものリアリズム(音楽もいつものとおりに、歌えば歌うし、楽器を奏けば楽器が鳴るリアリズム)で、観ている分には相も変わらずえらく楽しい。
もう疲れたから監督業はやめるそうだが、記念すべき最後の作品に何で、この作品を選んだんだか、最後まで人を食った爺さんだな。
(系列としてはピエールルイス(こいつは20世紀かな)のビリティスの唄みたいな感じなんだろうけど(舞台を過去にすることで自由にエロを描くという手法)、もうでたらめし放題で、顎が長すぎてベールが突っ張っているところとかおかしくて死ぬかと思った)
で、ロビーのちらしを眺めていたらクエイ兄弟のDVDがばかばか売られるらしい。アマゾンにもいくつか出ている。すさまじい定価がついているので、買うならアマゾンかな、という気はするが、しかし、1000セット限定のコレクターズDVD BOXはアマゾンには現時点では出ていない。
ストリート・オブ・クロコダイル(大鰐通り)が収録されているVHSは持っているけど、買い直したほうが良いように思うので、たぶん、買うのだが、DVD BOXがいいなぁ。
ブラザーズ・クエイ ショート・フィルム・コレクション [DVD](ブラザーズ・クエイ)
おれは相当気にいったので、ピアノチューナー・オブ・アースクエイクも買っておきたい(と考えると、やはりDVD BOXか)。
で、予告編で、カトリーヌドヌーブが出て来て、傘屋が出て来て、ルグラン節が鳴り響く。観たことないので、今度こそ観たい、シェルブールの雨傘だ。
しかし、すぐに続けてカサベテスじゃなくてジョージチャキリスがにたにたしながらオレンジの服で椅子に逆向きに腰かけて、逃げたインドかぶれの女の子の代わりに双子をくどくシーン、で、OKのカット、そのままトンピリプ、トンピリペ、トンピリパピプペポの歌かと思うと、予告編だからだろうがいきなり冒頭のバレエ教室のシーンが始まり、私たちは双子の姉妹の歌が始まり、ラブチェアで脚を使った双子のハートのシーンとなり、何億倍も心がゆれ動かされる。やっぱ、おれは、ロシュフォールの恋人たちが好きだ。おれの一番好きな映画だなぁ。というわけで、シェルブールの雨傘はどうでもいいから、また映画館でロシュフォールの恋人たちを観られるという事実に嬉しくなった。
ロシュフォールの恋人たち [DVD](カトリーヌ・ドヌーブ)
本当に、おれは、ゴダールよりもロメールよりもトリュフォーよりも、ドゥミが好きだなぁ。
(たぶん、ロシュフォールのマクシミリアンのパートがうっとうしいので、シェルブールのほうは、きっとこのパートと同じようなトーンなんじゃないかと想像して敬遠しているわけだが、機会を逃すとそのまま観られなそうな気もするので、シェルブールのほうも、たぶん観に行く。しかし、やはり、ロシュフォールのほうが観たい。まったく何百回観たことか)
何をしてもHKCR\CLSIDの下にASRが登録できないので閉口する。しかし生成できる。
考えてみたら64ビットWindowsではHKCR\CLSIDは64ビット用になっていたのか。
結局 HKCR\Wow6432Node\CLSID の下に登録されていた。
VBScriptからASRを呼ぶテストをしていて妙な現象に悩む。
VC6++から実行するとデバッグモードだろうが、リリースモードだろうが実行できる。
しかし、CMD.EXEからCScriptを指定しようが直接vbsを指定しようが、オブジェクトの生成に失敗する。
まったくわからん。
で、上のレジストリからふと、64ビットcscriptが実行されているのが原因ではないかと気づく。
おそらく、Win64は賢く32ビットアプリケーションのVC++6が実行する場合は32ビットアプリケーションを実行しているので(PATHは\windows\system32\cscript.exeを指定しているわけだが)、そこのシームレスさにだまされていたということだ。
で、探してみたら、C:\windows\syswow64\cscript.exeというのが見つかる。
で、これを指定してvbsを実行すると無事、ASRの実行に成功。
なるほど、という感じだ。
それにしてもMSHTAは、このあたりをどうしてうまく処理できるんだろうか?
YARVの動きに詳しい方、助言をお願いします。
以下、状況を手短に説明。
ASRのテストをしていたら、イベントハンドラ付きのテキストを設定するところでエラーとなる。
たとえば以下のコード
Window.document.getElementById('foo').innerHTML = '<div id="x" onclick="funcall()">hello</div>'
この呼び出しを行うと、次の動作をする。スレッドは2つある。1つはMSHTAのスレッド、もう1つはRubyのスレッドだ。それぞれスレッドMとスレッドRとする。
_unk = Proc.new { funcall() }
(スレッドM)これは困った。Ruby-1.8.7では特に問題なかったのだが。
原因は、おそらくWin32OLE#method_missing呼び出し中(innerHTML=メソッドの呼び出し)の再入にあるのだろう。
この時のスレッドRのスタックトレースは以下となる。
cfp->iseq == 0 直前のcfp cfp->iseq = 0 cfp->flag 0x0061 (& VM_FRAME_FLAG_PASSED == 0) vm_get_ruby_level_caller_cfp(rb_thread_struct * 0x001b6ff0, rb_control_frame_t * 0x029bfed0) line 152 eval_string_with_cref(unsigned long 0x02f23cc4, unsigned long 0x02fff1e8, unsigned long 0x00000004, RNode * 0x02fff1c0, const char * 0x03000518, int 0x00000000) line 707 + 16 bytes eval_under(unsigned long 0x02f23c60, unsigned long 0x02f23cc4, unsigned long 0x02fff1e8, const char * 0x03000518, int 0x00000000) line 941 + 27 bytes specific_eval(int 0x00000003, unsigned long * 0x032dc934, unsigned long 0x02f23c60, unsigned long 0x02f23cc4) line 979 + 27 bytes rb_obj_instance_eval(int 0x00000003, unsigned long * 0x032dc934, unsigned long 0x02f23cc4) line 1017 + 21 bytes call_cfunc(unsigned long (void)* 0x02c394a0 rb_obj_instance_eval(int, unsigned long *, unsigned long), unsigned long 0x02f23cc4, int 0xffffffff, int 0x00000003, const unsigned long * 0x032dc934) line 286 + 15 bytes vm_call0(rb_thread_struct * 0x001b6ff0, unsigned long 0x02f4bf44, unsigned long 0x02f23cc4, unsigned long 0x00000ad0, unsigned long 0x00000ad0, int 0x00000003, const unsigned long * 0x032dc934, const RNode * 0x02f449b0, int 0x00000000) line 71 + 31 bytes rb_funcall2(unsigned long 0x02f23cc4, unsigned long 0x00000ad0, int 0x00000003, const unsigned long * 0x032dc934) line 412 + 1290 bytes safe_funcall(unsigned long 0x032dc92c) line 142 + 27 bytes rb_protect(unsigned long (unsigned long)* 0x10034840 safe_funcall(unsigned long), unsigned long 0x032dc92c, int * 0x032dc940) line 647 + 31 bytes CRubyWrapper::rb_funcall_with_string2(CRubyWrapper * const 0x030610f8, IRubyEngine * 0x03063ac8, unsigned long 0x02f23cc4, unsigned long 0x00000ad0, long 0x00000000, long 0x00000029, unsigned char * 0x0056834c, unsigned char 0x00, tagVARIANT * 0x032dcbc8 {VT_EMPTY}, IActiveScriptError * * 0x00571e90) line 243 + 18 bytes RPCRT4! 75ee43b6() RPCRT4! 75f70cc6() RPCRT4! 75f7093e() <----LRPCによってスレッドMから再入 OLE32! 77389759() OLE32! 773896f3() OLE32! 772a9d67() OLE32! 772a9c5c() OLE32! 772aaab0() OLE32! 7738961b() OLE32! 77389498() OLE32! 77389aa2() OLE32! 772aa8ea() OLE32! 772aa8a9() USER32! 763a8807() USER32! 763a8962() USER32! 763a8aad() USER32! 763a8b00() OLE32! 7727b0a6() OLE32! 77278a9d() OLE32! 772789d7() OLE32! 7727898f() OLE32! 7727ac88() OLE32! 7727ad74() OLE32! 77387c28() OLE32! 773889d4() OLE32! 7727ad2e() OLE32! 7727ace0() OLE32! 7729e688() RPCRT4! 75f71074() <--- LRPCでスレッドMのDOM操作 RPCRT4! 75f7102b() DISPEX! 727f2576() DISPEX! 727f2a43() CRScriptCore::fole_propertyput(unsigned long 0x001b85dc, unsigned long 0x02fff1fc, unsigned long 0x02fff210) line 866 + 54 bytes CRScriptCore::foleex_missing(int 0x00000002, unsigned long * 0x032ddf60, unsigned long 0x001b85dc) line 1233 + 22 bytes call_cfunc(unsigned long (void)* 0x100012b2 CRScriptCore::foleex_missing(int,unsigned long *,unsigned long), unsigned long 0x001b85dc, int 0xffffffff, int 0x00000002, const unsigned long * 0x032ddf60) line 286 + 15 bytes vm_call0(rb_thread_struct * 0x001b6ff0, unsigned long 0x02f23ecc, unsigned long 0x001b85dc, unsigned long 0x00000188, unsigned long 0x00000188, int 0x00000002, const unsigned long * 0x032ddf60, const RNode * 0x02f23e54, int 0x00000000) line 71 + 31 bytes rb_funcall2(unsigned long 0x001b85dc, unsigned long 0x00000188, int 0x00000002, const unsigned long * 0x032ddf60) line 412 + 1290 bytes vm_method_missing(rb_thread_struct * 0x001b6ff0, unsigned long 0x000031e4, unsigned long 0x001b85dc, int 0x00000001, rb_block_struct * 0x00000000, int 0x00000000) line 418 + 25 bytes vm_exec_core(rb_thread_struct * 0x001b6ff0, unsigned long 0x00000000) line 999 + 1881 bytes vm_exec(rb_thread_struct * 0x001b6ff0) line 1077 + 13 bytes rb_vm_invoke_proc(rb_thread_struct * 0x001b6ff0, rb_proc_t * 0x02fd9460, unsigned long 0x02f23cc4, int 0x00000001, const unsigned long * 0x032def50, rb_block_struct * 0x00000000) line 571 + 1117 bytes proc_call(int 0x00000001, unsigned long * 0x032def50, unsigned long 0x001b87d0) line 525 + 33 bytes call_cfunc(unsigned long (void)* 0x02c9cb30 proc_call(int, unsigned long *, unsigned long), unsigned long 0x001b87d0, int 0xffffffff, int 0x00000001, const unsigned long * 0x032def50) line 286 + 15 bytes vm_call0(rb_thread_struct * 0x001b6ff0, unsigned long 0x02f2f628, unsigned long 0x001b87d0, unsigned long 0x000015a0, unsigned long 0x000015a0, int 0x00000001, const unsigned long * 0x032def50, const RNode * 0x02f2f5b0, int 0x00000000) line 71 + 31 bytes rb_funcall2(unsigned long 0x001b87d0, unsigned long 0x000015a0, int 0x00000001, const unsigned long * 0x032def50) line 412 + 1290 bytes CRubyWrapper::InvokeRuby(unsigned long 0x032def40) line 513 + 33 bytes rb_protect(unsigned long (unsigned long)* 0x10001af0 CRubyWrapper::InvokeRuby(unsigned long), unsigned long 0x032def40, int * 0x032defb0) line 647 + 31 bytes CRubyWrapper::rb_invoke(CRubyWrapper * const 0x030610f8, IRubyEngine * 0x03063ac8, unsigned long 0x001b87d0, unsigned long 0x000015a0, tagDISPPARAMS * 0x0056f9b8, tagVARIANT * 0x005975d0 {VT_EMPTY}, IActiveScriptError * * 0x00597608) line 346 + 18 bytes RPCRT4! 75ee43b6() RPCRT4! 75f70cc6() RPCRT4! 75f7093e() <--- LRPCでスレッドRからASRのCOM wrapper経由でinstance_evalが呼ばれる OLE32! 77389759() OLE32! 773896f3() OLE32! 772a9d67() OLE32! 772a9c5c() OLE32! 772aaab0() OLE32! 7738961b() OLE32! 77389498() OLE32! 77389aa2() OLE32! 772aa8ea() OLE32! 772aa8a9() USER32! 763a8807() USER32! 763a8962() USER32! 763a8aad() USER32! 763a8b00() RubyWrapper(void * 0x0033e694) line 141 + 12 bytes _threadstartex(void * 0x03063f20) line 227 + 13 bytes <--- 本当のトップレベル KERNEL32! 7743e3f3() NTDLL! 77cecfed() NTDLL! 77ced1ff()
途中でLRPCやOLEがスタックを変えてはいるが、YARVのフレームやスレッドを破壊しているわけではない(実際、thおよびcfpはASRのinstance_eval呼び出し時はWin32OLE#method_missingの時のものを取り出している。したがって状態はcall_cfunc中にcall_cfuncされた状態だと思える、というかどういう状態が正しいのかYARVを読み切れていない)。
c呼び出しが重なるのが原因かと思って小さな再現プログラムを作ったが、その方法では再現しない。
昨日の奴の小さな再現プログラムが作れたのでチケット切った。
rb_obj_instance_evalを呼ぶと問題なかったり。
でも行番号が指定できない。
追記:というのは間違い。str, fname, line_noを受け付ける(ブロックを与えることもできる)
うーん、HTAのパターンなら、後から呼べるように作ったProcを覚えておくインスタンス変数が欲しいだけだから、全然evalする必要はないんだよなぁ。
問題は、ActiveScriptだから、他の呼び出しパターンがあり得ることと、スレッドを越えてLRPCするから、Rubyスレッド側で用意するLRPC用エントリーを絞りたい(絞るならinstance_evalとmodule_evalを用意しておけばたいてい事足りる)こととかな。
書影からの見た目の感想。
アーキテクトの審美眼 (DBMagazine SELECTION)(萩原 正義)
ビジネス書みたいだなぁ。全然、審美的ではない表層。でも、それでいいのかな(ビジネス的には、つまりターゲットに合わせるという意味において)?
2chで見たのだが、ASR(というパッケージではなく、ActiveScriptRuby=RScript18.dllのこと)が以下のHTAの実行に失敗し、結果的にスタックオーバーフローで死ぬ。
<html><head><hta:application> <script language="RubyScript"> alert('r'); </script> <script language="JavaScript"> alert('j'); </script> </head><body></body></html>
ActiveScriptingのホスト(この場合、MSHTA)は、スクリプトが利用するホスト側オブジェクトをIActiveScript::AddNamedItemメソッドを呼び出して登録する。MSHTAの場合は、windowがそれに当たる。
ASRは、この呼び出しを受けると、IActiveScriptSite::GetItemInfoメソッドを呼び出して、必要な情報を得て、Rubyのスクリプトがwindowオブジェクトを操作できるようにする。この時、スクリプトからのアクセス用にWindow、@windowの2種類の変数を用意する。それに加えて、ある時点から、JScript同様にグローバルなオブジェクト(AddNamedItemメソッド呼び出し時にSCRIPTITEM_GLOBALMEMBERSフラグが指定される)については、直接スクリプトが記述できるように(あたかもmainオブジェクトのprivateメソッドのように)登録しておく。
なお、ここでの問題とは直接関係しないが、イベントを通知するための仕組みは、ホストに対してIDispatch*を与えることで実現している。たとえば、HTML要素にonclick属性を指定すると、ホストは、IActiveScriptParseProcedure::ParseProcedureTextメソッドを呼び出し、スクリプトのパース結果をCOMの呼び出し可能なオブジェクトとして要求する。したがって
<input type="button" id="eventSource" onclick="alert('hello')">と書くと、alert('hello')を実行するIDispatch*をActiveScriptは生成し、それをホストへ与える。ホストはイベントを通知したくなると、該当IDispatch*のデフォルトメンバをInvokeする。ASRはこれをProcオブジェクトとして実装している。
本題に戻ると、おそらく、スクリプト側での拡張を認めるためだと思うが、ホストは、AddNamedItemメソッドで設定したオブジェクトについても、IActiveScript::GetScriptDispatchメソッドを呼び出し、ActiveScript側のオブジェクトのIDispatch*を取りに来る。
このとき、RubyScriptのみがMSHTAのスクリプトとして実行されていると、以下の動きとなる。
ASRは、この処理を、最初、以下のように実装していた。
MSHTA上にRScriptのみしか存在しなければ、ホストはGetItemInfoに対して自分が保持する(この場合であれば)windowのIDispatchEx*を返すので、そこで終了する。
ところが、JScriptが共存すると、話が異なる。
ホストはJScriptに対してAddNamedItemを呼ぶ。JScriptはGetItemInfoを呼ぶ。ホストは拡張している可能性からASRのGetScriptDisaptchを呼ぶ。ASRは、上記のテンポラリオブジェクトのためにGetItemInfoを呼ぶ。ホストは拡張している可能性からASRのGetScriptDispatchを呼ぶ。ASRは、上記のテンポラリオブジェクトのために……スタックオーバーフローする。
結局、ホスト側のオブジェクトとしてすでに登録されていれば、そのIDispatchEx*をGetScriptDisaptchの結果として返すことで、このループを回避できる。
という修正をしたASRを作った。
msiは、たぶん、1.8.7の次期パッチ版がもうすぐリリースされると思うのでその時作ることにして、とりあえず、RScript18.dllのみのzipをダウンロードページに置いた。
ASRは一応、完成した(ソース)。
しかし、soleb.rbを実行すると、うまく行かない。Swinにもう少し修正が必要なようだ。具体的には、実行すると表示(ASCIIのところ)がおかしく、最終的に、
C:/PROGRA~2/RUBY-1~1.1/lib/ruby/vendor_ruby/1.9.1/vr/vrcontrol.rb:672:in `encode': "\xE6\x8D\x81" from UTF-8 to Windows-31J in conversion from UTF-16LE to Windows-31J (Encoding::UndefinedConversionError)
となる。
とりあえず、これはこれとして、ASRのサンプルとしての意味もあるのでsolebの真似をHTAで作ったholebというのを作ることにした。
その過程で、スレッドピンポンでinstance_evalすることになったりしたのであった。
で、これが終わったらリリースするのだが、最近、昼の仕事が忙しいのであった。なので、もうちょっとかかりそうな雰囲気。
WEB+DBにt-wadaさんやkwachさんとDRYの記事を書きました(書影がアマゾンに出ているくらいだから、もう書いてもいいだろうと思うので書いている)。
もしかしたら、相当かあるいはちょっと、衝撃的あるいは挑発的な、内容かも知れません。少なくとも、おれが読んだら、これ書いたやつは(ちゃんと読まなければ)ばかじゃないかと感じるかも(特にパート2と4)。ある意味、そう読まれたら、それはそれで成功だし、そこで、なぜ、これを書いたやつはばかだと感じるのか自答できれば、それは良いことだし、そうでなく、そこから何かしらの教訓なり考え方なりを得られれば、もちろん、それこそ望むところです。それでも、考察しているのはおれだけど、必ずしもおれがその事象に賛同しているわけではないというのは読めるようには書いているつもりだけど。
もっとも、あーふつーふつー(平仮名にすると別の意味が出てくるのが厄介な点だな。漢字で書くとこの文体に合わないのでひらがなにしているだけで、深い意味はない)と感じるかも知れないので、それはそれで良いことで、ふつーと感じるのなら、そりゃDRYな人生を歩んでいる証拠で、それは素晴らしい。
記事にも書いてあるけど、このあたりを参考にしました。
(なぜ、この本が? と思ってくれればいいね)
達人プログラマー―システム開発の職人から名匠への道(ハント,アンドリュー)
(これは当然)
それから、Go to statement considered harmfulと、MANAGING THE DEVELOPMENT OF LARGE SOFTWARE SYSTEMS。(これまたDRYの文脈からは訳がわからない参照のはずだと思うけど、どうかなぁ)
少なくとも、ダイクストラの「GOTOステートメントは有害と考えられる」(ステートメントが付いているのがすごく重要なんだけど、わかっているのかな?)については、俗流解釈が多くてうんざり、というのもあるかも。これはプログラミング言語の設計に関する考察なんだけど、プログラムの書き方についての説教だと受け取っている人がいるように感じることとか。現物を読まなければ、そう思うのはしょうがないけど。
というように(と書かれていない説明を受けて結論を導く)、ちょっとWEB+DBの読者の指向性とは(少なくとも表面的には)異質な方向で書いてみたつもりです。そのほうが幅が出ておもしろいだろうと思ったし。
追加:なんか見つけたけど、木村泉先生のGo to statement considered harmfulの感想(追記:リンクを修正)。
さて、動くようになったかと思ったが、そうではなかった。
ので、直した。ダウンロードのページ
以下のようなスクリプトが動かないとのことだった。
<script language="RubyScript"> def foo alert('foo') end </script> <script language="JScript"> function bar() { foo(); } </script>
といった、言語間のインターオペラビリティでエラーとなる。
ホストから見れば、Rubyのfooも、JScriptのbarも、どちらもwindowオブジェクトのグローバル関数だ。したがって、windowのIDispatch*で自分が知っている関数について(この場合はfoo)は、自分でwindowのIDispatch*からJScriptが呼べるようにしてやらなければならない。
つまり、windowのIDispatch*を使ってデリゲートを実装する必要がある。
が、スレッド間のマーシャリングが厄介で、と最初考えたが、良く考えたら、JScriptやホストがRubyのスレッド内から呼び出すはずはなかった。したがって、GetScriptDispatchに返すwindowのIDispatch*をラップしてやり、そこのGetDispIdやInvokeExで呼び出しを切り替えれば良いことになる。
なお、MSDNには優先順位は書いていないので、ホスト優先とすることにした。
つまり、
def alert(x) @window.alert(x) end
は、一見するとうまく動きそうで、かつ、Rubyスクリプト内から呼ぶ分には、正しく動くが、仮にJScriptから呼び出そうとすると、ASRは、windowのalertを先に見つけ、windowのIDispatch*へ委譲してしまうので、Ruby側のalertは呼ばれない。名前のバッティングはしてはいけない。
おもしろかった。
作ってしばらく遊んで、なんか忙しくなって放置していたGainerXを思い出したので、レポジトリを公開しておくことにしたり(releaseディレクトリの下にビルド済みocxも置いてある)。
vb6ディレクトリに、VB6のフォームに貼り付けて操作したりイベント受けたりするサンプルが置いてあるけど、GainerX自体はどこまで実装したか忘れちゃった。
確か、元のGainerのJavaのアプリケーションレベルドライバがぽこぽこ取りこぼすのに不快になってC++でアプリケーションレベルドライバを作ったはず。だから、相当、細かい解像度で入出力ができたような記憶はあるんだけど。
GainerXは、VC++2008のネイティブC++プログラムで、WaitCommEventと、MsgWaitForMultipleObjectsを使ってイベントドリブンなIOを専用スレッドで実行するようにしている。
メインスレッドのCOMコンポーネントとの通信にはCOMマーシャラではなく、Windowsメッセージを利用して最少のオーバーヘッドで実現とか、そんな感じ。
とか、書いていてふと気づいて検索すると、2008年7月で既に公開していた。というか、RubyKaigi2008でごとけんさんにおもしろいから遊べとそそのかされたわけだから、すぐに作ったみたいだ。
+GAINER―PHYSICAL COMPUTING WITH GAINER(GainerBook Labo + くるくる研究室)
Ruby-1.9.1用ActiveScriptRuby(というActiveScript。パッケージではありません)をリリースします。
ダウンロードページに注意がありますが、ASR191は、RScript19.dll、GRScript19.dllおよびholeb.hta(HTA版簡易OLEブラウザ)のみのパッケージで、Ruby-1.9.1-p*.msiに対するAddOnです。インストール先ディレクトリは、Ruby-1.9.1-p*.msiをインストールしたディレクトリを指定してください。
ASR191をインストールすると、Ruby-1.9.1プログラムフォルダに、holeb.htaというHTMLアプリケーションが登録されます。これは、ActiveScriptRuby(というRuby 1.8 パッケージ)のsoleb.rb(シンプルOLEブラウザ)のHTMLアプリケーション版で、RScript19.dllとRuby1.9.1-p*を利用して動作します。ソースはインストールディレクトリを参照してください。
なお、ActiveScriptRuby(という1.8用パッケージ)とASR191を共存させて、Ruby 1.8とRuby 1.9.1を使い分けるには、ProgID(HTAであれば、scriptタグのlanguage要素で指定する名前)に、バージョン番号をつけます。ASR 1.8は、バージョン1(RubyScript.1)、ASR191は、バージョン1.9(RubyScript.1.9)です。バージョンなしProgIDのRubyScriptは最後にインストールしたパッケージとなります。
RubyのWindows用パッケージ(うささんのzipやInstantRailsはプリミティブなので、以下の話とは合わない)には、ASR以外にもOne Clickなどがあるが、この2つについては、端的にWindowsの作法にしたがっているかどうかによる致命的な差がある。
ASRはきちんと作法にしたがっている。したがって、ASRとRuby-1.9.1の2種類のパッケージがネイティブに共存する。1.8を使いたければRuby-1.8スタートメニューからRuby Consoleを実行すれば良いし、1.9.1を使いたければRuby-1.9.1スタートメニューからRuby-1.9 Consoleを起動すれば良い。
しかし、One Clickは、よほど妙ちきりんなクラッジを駆使しなければ、1.8と1.9.1を共存させて、かつ使い分けさせることはできないだろう。
なぜなら、あの連中はWindowsをUnixか何かと勘違いして、環境変数にRubyのパスを設定しているからだ。ばかじゃねぇか?
というわけで、そのシステムの作法にしたがうということの重要性はマイグレーションが必要となったときに、顕著な差となって現れる。というか、PATH環境変数の設定を放置していて結果ラッキー。
音をプログラムから扱う方法で、MIDIは大体わかるしそれなりにプログラムも組んでいるわけだが、なんというか、自由度が低くてつまらない。 別に楽音だけで遊ぶ必要もないわけなので、波の音を使ってみたいのだが、知らないものは知らないので、なんか本でも読んでみるか、とジャスコの3階の本屋で見かけたので買ってみた。
WAVプログラミング .NET C#で学ぶ音響処理(北山 洋幸)うーん、値段のわりに微妙というか、ちゃんと読まずに買ったおれも悪いのだろうが、半分ほどは20分もかからずに読み終わってしまった。
最初にwavファイルのフォーマットについて説明がある。なるほど、そうなのか。というところまでは良い。C#を使うけど、単純にBinaryStreamを使って上から下へプログラムを流すぜ、というのも本で読むには悪いスタイルではなく、むしろ読みやすいからこれもOK。
しかし、右チャネルを無音にする。左チャネルを無音にする、交互に無音にする、という1〜2行違うだけの見開き2ページくらいのプログラムがえんえんと続くのにはいささかまいった。
で、ようやく、16ビットのwavファイルを8ビットに変換する、という少しはそれっぽい処理が出て来て、見ると、これまた1行(ヘッダの書き出しは別として)違う。
で、その式が(引用ではなくコードを思い出しながら書いている)、short L = binstream.readShort(); deststream.writeByte((byte)((L >> 8) + 128))
というような処理で、なぜ、16ビットを8ビット右シフトして128足して下の1バイトを取り出すことで変換できるんだ? と不思議になる。(実際にwavファイルを変換して聴けば良いのだが、電車の中で読んでいたのでそれは無理。というか、今やればよいので後で試す)
(細かなことを言い出すと、型の使い方が不自然な気がするが、Javaと違ってC#のbyteは符号なしだからか、というかsbyteを使わないのはなぜだろうか、とか)
1バイトは-128〜127で、2バイトなら-32768〜32767だ(と書いて、少し怪しいことに気づく。irbだとこの辺がちょっと弱いな。Bignumは万能ではない)
16ビットを8ビットにするというのだから、全体の間隔を間引く必要があるんじゃないかな、ということだ。
実際に、この式を利用して16ビット整数を8ビット整数に変えるとこんな感じになる。
public class b16 { public static void Main() { int[] ss = { 0x8000, 0xf000, 0xff00, 0, 1, 0xff, 0xfff, 0x7fff }; foreach (int s in ss) { System.Console.WriteLine("{0} -> {1}", (short)s, (sbyte)((s >> 8) + 128)); } } }実行すると
-32768 -> 0 -4096 -> 112 -256 -> 127 0 -> -128 1 -> -128 255 -> -128 4095 -> -113 32767 -> -1
どうにも腑に落ちない。なんともアナログから取り出した数は不思議な世界だな。というわけで実際にやってみるか
追記:試そうと思ったがwavファイルなんてどこにも入ってないじゃん。今のWindowsはサンプルもwmaなのか……この後に本題のカラオケ用に中音を抜くとか、エコーをかけるとかの加工の話に入るので、何かwavファイルを入手しないとどうしようもないなぁ
<script language="RubyScript.1.9"> @counter = 0 def start() @timerid = setInterval(timeout, 1000) end def timeout() @counter += 1 document.getElementById("disp").innerHTML = @counter.to_s end </script> </head> <body> <input type="button" onclick="start()" value="start"> <div id="disp"></div>
が、実行すると例のCant't eval on top of Fiber or Threadが出て目の前が暗くなる。
しばらく考えてもわからない。で、いろいろタイマー値を変えてみると、どのような値を設定してもすぐにタイマーがエキスパイアして、しかも次のインターバルが来ない。
それで、やっと思い当たる。JavaScriptではないのだから、メソッド名を書いたら、それはメソッド呼び出しになる。
@timerid = setInterval(Proc.new {timeout}, 1000)
に修正して落着。
前回は西の代わりに東へ行ってしまったが、今回は東の代わりに西に行ってしまって、遅刻×4人分。ごめんなさい。
というわけで入った時には原先生の講演はもう始まっていて、博士は計算できないけど、それを別のもので補えばいいじゃんというようなくだりになっていた。
そこで原メソッドという、スライドに講演者に対する指示を埋め込むという、公開メタデータのデモ。
それから、algebraの説明。
しかし、リンクを貼ろうとGoogleでruby algebraで検索するとringが出てくるので、これは見つけにくい(と、講演の話ではなく、さっき実際に試していたときの話となる)。
1.9.1にインストールしようとすると、ftoolがないよといってinstall.rbがエラーになるので(もっともクラス変数の扱いの差で動かないらしいけど)、素直に1.8.7のほうにインストールしてみる。
irb(main):002:0> require 'algebra/polynomial'
=> true
irb(main):003:0> P, x = Algebra::Polynomial.create(Integer, 'x')
=> [P, x]
irb(main):004:0> f = x**5 - x**4 + 2*x - 2
=> x^5 - x^4 + 2x - 2
irb(main):005:0> p f.factorize
(x - 1)(x^4 + 2)
=> nil
(algebraって、アブラカダブラの一種とかと思ってたが、代数のことなのか)
(で、とちぎRuby会議へ復帰)
その後は、筆記用具自慢の話になる。手に合う筆記用具を使えば、気持ちがいいので良い作業ができるというような話。それは確かにそうだな、と、自分のRealforceについて思いをはせる。
確かに触っていて気持ちが良いほうがいいし、作業中はずっと触っているのだから、触感はすさまじく重要だ。
で、次にごとけんさんの20世紀Rubyの話として、池澤さんと咳さんの出会いに対する介入から、LCのサブカンファレンスとして実行されたPRCの思い出話とか。
続いてLTで、今なら韓国のA+ショップ(といっていたような)でPower MAC(追記:寝ぼけてますね、Powerって。ツッコミ参照)を買うと4割以上引きで買えるけど(税金返還証明書の入手をお忘れなく。空港で返還してもらうのに必要)、iPodは空港の免税店で買うのが吉とか、dRubyを使ってユニットテストを並行実行する話とか、タイマーを作る話とか(を聞いて、HTAで作ってみようとしてはまったのが上のエントリー)、いろいろ。
最後に通常版torubyでdRuby演習。たくさんのコンピュータがあって相互接続できるのは、やはりおもしろいと、あらためて実感。
スタッフのみなさん、ありがとうございました。
ごとけんさんもそういえばスティーブンスを読めと言っていたなぁと、突然、ステーブンスのあさましを繰り広げてみたり。
詳解UNIXプログラミング(W.リチャード スティーヴンス)
……おれ、これは読んでないし、持ってもいない気がしてきた(ということはたぶん持っていないし読んでいない)
というわけで、おれとスティーブンスの出会いは、
UNIX Network Programming(Stevens, W. Richard)
これだな。1990年出版というところもそれっぽい。
急にといっても前兆はあったのだが、LANが世の中にやってきて、それまでのHDLCとかBSCとかではなくCSMA/CDの上でTCP/IPやUDPを使っていったりきたりする必要がでてきて、さて、どうするかというときに、bit別冊のコマーのTCP/IP VOL1とVOL2、しばらくして原書のほうが3巻(BSDソケットだと思う、というのはSYSV UNIXはstream(TLSとかいったような記憶があるが忘れてしまった……調べた。TLIだ)なので、どうもコード例がいまいちだったので3巻が読みたかったはず)があるので、赤い本を3冊そろえて読んだ。
Internetworking With Tcp/Ip: Principles, Protocols, and Architecture(Comer, Douglas E.)
(これそうかな?)
読んだのはいいが、いまひとつピンと来ない。
というときに、白いスティーブンスの本を見つけて、こりゃいいや、となった覚えがある。で、ご多分にもれずだと思うが、最初はスティーブンスの実装を眺めながらTFTPを実装していろいろ試してみたりした。
が、考えてみれば、それから20年近くたっているのだ。
古典は古典で悪いものではないが、現代は現代で良いものだ。それなりの学び方ってものもあるのではなかろうか。
というわけで、別にStevensを読む必要もなかろうとは思うが、はて、では何が良いのかと聞かれるとわからない。
UNIXプログラミングと限定すれば、UNIXではないものの
ふつうのLinuxプログラミング Linuxの仕組みから学べるgccプログラミングの王道(青木 峰郎)
まあ、ふつうでいいんじゃないかと思うが、ネットワークにはふつうはない。し、ネットワークのようにIOで脚を引っ張られるタイプのプログラミングについては(スケールしなければならないサーバーは別として。でも別とするとだめかも知れないが)、別にCでソケットたたかなくても、Rubyとかでいいじゃんの、HTTP限定でAjax(JavaScript)とかでいいじゃんという気もしないでもない。気のせいだが。
っていうか、プロトコルを自分で作らないネットワークプログラミングってのは、あまりおもしろくないような。と書いた瞬間から、RESTのAPIってプロトコルを決めているような、と気づかなくもない。アプリケーションプロトコルのさらに上位プロトコルを決めるというのは、多層化の層が厚くなってきたのだから、それで良いのだ、とも言えなくもない。
こないだ動かしてみた原先生のalgebraだが、因数分解の結果がでるまで明らかに待たされる。
なんで1.8.7で動かしたかといえば、install.rbがftoolを利用していて、ftoolが入っていないからであった。
というわけで、setup 3.4.1を使ったらどうだろうと、setup.rbを入れてインストールしてみた(ruby setup.rbを実行)。元々install.rb用のディレクトリ構成なのでsetup.rbで問題なくインストールできた。
で、動かしてみると少なくとも、多項式の因数分解はできた。
以下のプログラムの実行結果を示す。
require 'algebra/polynomial' require 'benchmark' puts RUBY_VERSION P, x = Algebra::Polynomial.create(Integer, 'x') f = x**5 - x**4 + 2*x - 2 puts(Benchmark.measure do 1.upto(10) do f.factorize end end)
x**5 - x**4 + 2 * x - 2の因数分解を10回実行した結果を取る。
1.8.7(MSWin32 P4 2.8GHz Vista64の32ビット環境上)
C:\test>ruby fact.rb 1.8.7 11.591000 0.016000 11.607000 ( 11.633000)
1.9.1(MSWin32 P4 2.8GHz Vista64の32ビット環境上)
c:\test>ruby fact.rb 1.9.1 7.909000 0.032000 7.941000 ( 7.977000)
という具合で、倍とは言わないが、1.4倍以上高速という結果だった。
こないだ、本だな整理していたらBOWの本が出て来て(箱に穴が空いている……と思ったけど、にわかに自信がなくなったが調べられない。なぜなら)捨てた。
だって、16ビットWindowsが無いんだからBOWだけあってもしょうがない。
というわけだが、全然別の文脈であるものを読んでいたらいきなりBOWが出て来て、ちょっと驚いた。
BSD on Windows 1.5―ユーザーズマニュアル(太田 博志)
(持ってたのは1.0のほうだと思う)
それにしても、BOWは、本当のハックだな。
トロツキーと初めて出会ったのは、赤塚不二夫のというよりも滝沢解の狂犬トロツキーで、なぜそういう物語になるかさっぱりわからなかった小学生のころのおれは、そのうち、トロツキーとかレーニンとかスターリンという、そのマンガに出てくる野良犬たちが実在した人物から名前を取っていることは知っていたから、歴史とか知ればわかるだろうと思っていた。
しかし、わかる歴史からは、良くわからず、でも、まあそのうちわかるようになった。
結局、トロツキーはスターリンが送り込んだ暗殺者を秘書として雇ってしまい、そしてピッケルで脳天をたたき割られて死んだ。
その半年ほど前に、遺書を書いている。
塀の下には、輝くばかりに青々した細長い芝生が見え、塀の上には、澄み渡った青空があり、日光はあたり一面にさんさんと降り注いでいる。人生は美しい。未来の世代をして、人生から一切の悪と、抑圧と、暴力を一掃させ、心ゆくまで人生を楽しませよ。
ライフ・イズ・ビューティフル [DVD](ロベルト・ベニーニ)
どうもその未来はそれから70年近く、つまり2〜3世代交代しているにもかかわらず、まだ来ていないかも知れない。
ペトログラードに鐘が鳴り、クロンシュタットの水兵達が悲鳴をあげる
そのころは世界を手にしていたのに。
永続革命(むしろ、永遠革命と訳すべきとは言われていて、永続ではいつまでたっても終わらないが、永遠であればいつでもどこでもやっている感がするかららしい)という概念は、権力は腐敗するという何かの信念に基づいてその上に構築したものだと思える。
事実、ソ連の1930年代以降の迷走というか爆走からもわかるわけだし、特に、レーニンが考え付いたらしい、過渡的な独裁という方法論の帰結としてもある程度は想像はつくだろう。
革命のコンテキストは無限のエクステントを持つということだ。
しかし、それが起きる条件というものがある以上、スコープはレキシカルなものだ。
レキシカルなスコープと無限のエクステントといえば、それはクロージャだし、それをブロックとして取り出せば継続となる。
その継続は、何かのはずみで再開される。
しかし、コンテキストは同じでも、ステートは先に進んでいる。
というように類比させると、コンティニュエーションの理解は楽になるだろうか。いや、なるまい。
それでも、今、この時に、キューバで作った継続を、ボリビアあたりで再開させようとした男の物語が人を集めているというのは、興味深い。
なんと、DVDが出るのか。わくわくわくわくわくわくまた、あの白い汚れた光り輝くシャツを着た天使じゃないなにかの映画を観られる。それは素晴らしい。
クエイ兄弟貯金はやめて、こっちを買う。いや、クエイ兄弟は買うかもしれないけど。
ある事情から1990年代の終わりから2000年代の初めのあたりに書かれた文章群を読んでいるのだが、非常に不思議な感じがする。
それと並行しながら、本棚を整理しまくり、捨てたり、テラダの倉庫に預けるための箱詰めとかをしている。
どえらく古いDDJJとかが出て来て、ぱらっと見て、捨てたり、どうしようか迷ったり。ここでも非常に不思議な感じがする。
たとえば、1996年10月のDDJJが出てきた。これまで2回のフィルタリングを通して残してきたのだが、最初のフィルタリングから先、読んだ覚えがないので、おそらく今回のフィルタを通過させても読まないだろう。したがって、捨てたほうが良さそうだ。
その不思議な感じの1つの理由として、個人的なものがありうる。一番、いろいろ吸収しまくる必要もあれば実際にしたせいで、特に印象が、その時点のもので形成されているという可能性だ。したがって、反応しやすい。
別の理由として、つまり感じている奇異の念の原因だが、当時は、何度目かの百花斉放の時期だったのかな、という感覚だ。百花斉放の時期には、さまざまな意見が出まくり、実践が行われ、それから淘汰され、そして静けさというか停滞がやってくる。
2004年前後のJavaというのは百花斉放の時期だったと想定する。ロッドジョンソンがEJBはだめだと言いだして新たなJ2EEについて語り出し、ソートワークスがパターンをエンタープライズにまで広げ始め、テスティングどうすべきかの模索があり、IDEは仁義なき抗争を繰り広げ、Strutsをコアとしてどう固めていくかについて語られ、XMLはあたりまえのものとなり、RPCではなくメッセージという流れが見えて来て……という具合だ。
それに対して、今は、停滞しているように見える。これも2種類考えられる。最初は個人的事情による。その時期の模索により、ある種のベストプラクティスパターンが形成でき、それの応用でしのげるようになったため、それほど外部の動きに対して敏感になる必要がなくなったため、新しい刺激への感覚が鈍ったという可能性で、これは十分ありうる。その場合は、最初の想定が誤りだということだ。であれば、百花斉放は常時行われていて、たまたま個人的な必要性によってのみ、そういう時期であったと規定される主観的なものだ。
その一方、本当に、大きくは停滞してしまった(同様にベストプラクティスが固まったため)という可能性もある。その過程で淘汰が行われ、生き残ったものが主流となり、新たなものがでにくくなる。そうであれば、最初の想定は正しく、百花斉放の時期と抑圧と停滞の時期は交互に繰り返されるというだけのことだ。次に花が次々と開くのはいつだろうか?
そういうときにこそ、足元を小さく長い尻尾を持ち、毛がふさふさした、不思議な生き物が這いまわりはじめ(と、恐竜時代の最初の哺乳類に思いをはせる)、敏感なものだけがそれに気づく。
それにしても、1996年のDDJJの『非同期用設計パターン』に出てくるIOUオブジェクトというのは、.NETのIAsyncResultのことだな、とか5年+5年以上の歳月を感じると同時に、まだ1990年代の技術がインフラ化されただけなのか(コモディティ化しているようには思えないが)、というちょっとしたがっかり感もある。
ジェズイットを見習え |
_ きしだ [Curlもアセンブラも、マクロ楽しかったです。 言語を拡張できる感じが楽しい気がします。 CSSとXSLTは、本体の..]
_ なるせ [CSSはマクロというには非力すぎますかねぇ。(変数くらい使わせてくれ) XSLT は言語というには冗長すぎますよね。..]
_ arton [やっぱそういう感じですね。>拡張できる、非力(ではない) とすると、下のほうのDSL以下がパワー不足なのが問題で、マ..]