Rubyで遊んだ日々の記録。あくまで著者視点の私的な記録なので、正確さを求めないように。
Rubyと関係ない話題にはその旨注記しているはず。なので、一見関係無いように見える話題もどこかで関係あるのかもしれません。または、注記の書き忘れかもしれません...
_ しかし、一時期はぜんぜん泣かずにいつもご機嫌な子だったのに、最近はよく泣くようになった。
うまく説明できないが、ご機嫌な子になる前は動物的に泣いていたが、今は人間的に泣いてる感じ。
要するに甘えまくりということか。
_ 話によると人見知りもあるということらしいのだが、実際に子供を連れて散歩してみると、話しかけてくる人にちゃんと愛想を振りまいている。モテモテ。
_ 19Bを作ったところで、御大に16Bというのをやられる。
悔しかったのでズルして6B。ズルした後で16Bをどうやるか気付く。
ああ、ズルはもうしないと誓ったはずなのに...
_ invert caseは御大がズルの方が圧倒的に短いことを発見して短くなった。
さ、先にズルしたのはあたしじゃないんだからねっ!
_ 途中でふとsort charactersを短くできる可能性に気付く。
最初はバブルソート、その後バケツソートに移行していたのだが、再びバブルソートに戻してみる。ふむ、10B近く短くなった。
そこからさらにコードを最適化して65B。
_ tennisに戻って128B。
とりあえずこんなもんか?
_ あ、Rubyでtennisでしょぼいの登録してますが、tennis.awkをupするつもりで間違えたのでした。しょぼん。
_ 1:38現在のLanguage RankingではRubyが総合・平均(1問しか解かれてないx86はスルー)とも1位。すばらしいね。
現在一押しのawkは総合3位。Pythonよりは常に上にありたい。
御大やshinhさんが頑張ってるsedもジリジリ来てる。
_ [ruby-core:10259]で発覚した問題の話。
簡単に言うと、SP1を適用したVC++8(Visual C++ 2005)でminiruby.exeまでは作れるけど正常に動作しない、というもの。
_ 前にVC++8対応した時もioinfo
構造体の中身が変更されていたのだが、どうやらSP1でまたなんか変わったらしい。
Cランタイムのソースが今回は出てきていない(たぶん)ので詳細はよくわからないが、おそらく後ろに新しいメンバ変数が追加されたのだろうという仮定の下に試行錯誤してみたところ、ioinfo
構造体のサイズが16バイト大きくなっていたということがわかった。
それを除けば、rubyが使っているメンバ変数に関しては意味もオフセットも変更されていないようではある。
_ 問題はこれをどう判定するか、なのだが、msvcr80.dllのバージョン番号を取ってきて判定することにした。泥臭い。
configure時にチェックすればいいか、と一瞬思ったが、古いmsvcr80.dllを対象にコンパイルされたバイナリもアセンブリバージョンのリダイレクト(%WINDIR%\WinSxS\Policies
を利用する奴)を使って華麗に新バージョンのmsvcr80.dllを利用するようになっているので、実行時にチェックするしかないらしい。くすん。
_ そもそも、__pioinfo[]
なんていう内部データを利用しようというのが根本的な間違いだと言ってしまえばそれまでなのだが、じゃあこれを捨ててfile系とsocket系を統合したIO機構を全部自前で実装しろと言われると...
_ こういう時は先達をチェックするに限る。
perlさんはPerlIOという素敵な仕組みを持ってるはずだが、前に見ようとしてそのコードの複雑さに断念した記憶があるのでとりあえずパス。
というわけで、pythonさんをチェックすることにする。2.5。
_ まず、file系は言うまでもなくfile
オブジェクト。
中身はstdioベースで実装されている。ふむ。
続いてsocketはというと、socket
モジュールのsocket
オブジェクト。
ここまではruby 1.8と同じだが、socket
オブジェクトはfile
オブジェクトとは直接の関係はなくて、Cのsocketの薄いラッパになっている。ふむ。
socket
オブジェクトからfile
オブジェクトへの変換はsocket
のmakefile
メソッドで行えるが、Windowsだとmakefile
メソッドはない(ので変換できない)らしい。
なるほど、割り切ってるなー。というか、rubyのWindows実装の諦めが悪いだけなのか。
_ と、いうわけで、rubyでもSocket
をIO
のサブクラスじゃなくして実装分離するのはどうですか?
... そうですねダメですね orz
_ 木村さんのパッチがruby_1_8に入った。すばらしい。
木村さん、knuさん、ありがとうございます。
口を出すだけで手を動かさない俺はちょっと吊ってきた方がいいな。つーかgolfしてないでやれよ>俺
_ 「アプリが不正終了の可能性 / 今度は「3000年問題」、Visual C++に」という話があることをさかきさんに教えてもらった。
_ 感想としては、「お前ら気付くの遅すぎ」と、「問題が出るのは3000年12月31日以降だっつってるだろ」といったところか。
あ、「32bit版でも起きるっつーに」というのもあるな。
なおリファレンスの_mktime64()
のところなんかにはちゃんとその制限時刻は書いてあるのだが、_mkgmtime64()
のところに書いてないのはいまいちではあるな。
#include <stdio.h> #include <stdlib.h> #include <time.h> main() { struct tm tm; time_t time; memset(&tm, 0, sizeof(tm)); tm.tm_year = 3001 - 1900; tm.tm_mon = 1 - 1; tm.tm_mday = 1; time = _mkgmtime(&tm); printf("0x%llx : %d-%02d-%02d %02d:%02d:%02d\n", time, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); time += 8 * 60 * 60; /* 8 hours later... */ tm = *gmtime(&time); /* good bye */ /* never reach here */ printf("0x%llx : %d-%02d-%02d %02d:%02d:%02d\n", time, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); }
というわけで、3001-01-01 08:00:00 UTCに死ぬ気がする。
この8時間はどっから出てきたんだろう? 米西海岸標準時か?
_ PerlIOの仕組みを自分なりにざっくりと今回の話に関係のある部分で捉えると、各IOごとに、規定されているプリミティブな関数群を用意し、処理系は実行時にIOごとのこの関数群を組み合わせて呼び出して高レベルの処理を行う、ということになるのだろうと思う。
つまり、各IO間では実装は可能であれば共有する(同じプリミティブ関数を使う)が、可能でなければそれぞれ個別の実装を用意する。
そういうフレームワークを作っておいて、処理系本体内での処理は各IOで共通化しているということになる。
_ で、WindowsにおけるIO処理はどうなってるかというと、えーと、rubyと同じだな。
__pioinfo[]
触ってるのも同じ。というか、rubyの実装がperlを参考にしてるんだろうと思うが。
うーん、ここでPerlIO_win32
とPerlIO_win32socket
とかいう感じで分離してたりしないかと思ったんだけど、そういうわけじゃないのかあ。
select()
に関してはsocketにしか効かなさげ。
_ ところで、win32/win32.hのioinfo
構造体の定義を見る限り、VC++8 SP1はおろかVC++8にも対応してないように見えるんだけど、ええんじゃろか?
これはstableじゃなくてdevelを見るべきか。
というわけで見たら、2006-11-06にVC++8には対応した模様... と思ったら2日後にその部分は巻き戻されてるな。
部外者だから事情はぜんぜんわからんけど、これは誤解で巻き戻されたんじゃないだろうか?
MSVCR80.dllで__pioinfo[]
いじるならこれは必須のはずなんだがなあ。
PerlCRTがあってそっちを使うからどうでもいいってこと?
_ いつもはexecするのがズルですが、今回はexecしないのがズルです。
あ、あたしはズルしてないんだからねっ!
_ James Edward Gray IIさんによる、まつもとさんとささださんのインタビュー。
現時点(03:20)でEPISODE Iのみなんだけど、ということはおそらく続くのだろう。
_ PerlIOの解説かと思ってwktkしてたら違った。
もちろん勝手に期待する奴が悪い。
_ 誰もやらなかったことを実際にやるということはとてもすごいことですよ。
ましてあの規模のものだし。
#include <stdio.h> #include <stdlib.h> #include <time.h> static void invalid_parameter(const wchar_t *expr, const wchar_t *func, const wchar_t *file, unsigned int line, uintptr_t dummy) { printf("somthing wrong!\n"); } main() { struct tm tm, *ptm; time_t time; _set_invalid_parameter_handler(invalid_parameter); memset(&tm, 0, sizeof(tm)); tm.tm_year = 3001 - 1900; tm.tm_mon = 1 - 1; tm.tm_mday = 1; time = _mkgmtime(&tm); printf("0x%llx : %d-%02d-%02d %02d:%02d:%02d\n", time, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); time += 8 * 60 * 60; /* 8 hours later... */ ptm = gmtime(&time); /* good bye */ if (ptm) printf("0x%llx : %d-%02d-%02d %02d:%02d:%02d\n", time, ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec); }
というわけで、普通(あくまでVC++8的に「普通」ってことだけど)にエラーをハンドリングすりゃいいんです。
かく言う私も1年ちょい前はこのこと知らなかったんだけどね。artonさんありがとうございます。
_ そもそもVC++7.1まではtime_t
の2038年問題(2036年問題だったかも)があったわけで、それが3001年まで延びてるんだからいいじゃん、という気がする。
範囲外の値の処理に関してはEINVAL
を扱えばよかったのがエラーハンドラの導入が必要になってるという面はあるが、ふつーにVC++8でコード書いたらどうせこのハンドラの導入は必要だし。
そもそも、無限の未来をtime_t
で扱おうなんて考えてるまともなプログラマはこの世におらんでしょ。
_ 個人的には、こんなどうでもいいことより、負のtime_t
値を受け付けてくれないことの方をどないかしてほしい。
_ 頭が開ききる前に採らないと食えなくなるよ! とか思ってしまう。
でも、世間では食べる時に頭を取っちゃう人もいるみたいだな。
_ trunkには放り込んであるわけだが、1.8はどうしよう?
入れないでコンパイルできないのもまずいが、adhoc過ぎてなんとなく入れたくないという思いもある。
誰かなんか改善案ないですか。
_ 寂しいので、みんなもっとawkやろうよ〜。
awk歴実質2週間程度という人が頑張ってる現状はよくない。
_ 問題は投稿できるらしいのだが、解答を投稿できない状態になっている。
一生懸命チート解答を考えたのに!(考えるなよ)
被捕捉アンテナ類
[Ant]
[Antenna-Julia]
[Rabbit's Antenna]
[Ruby hotlinks]