観察日記 2010-02-17

Float の仕様

Ruby の Float は C の double 型のラッパーなのだが、C の double 型の定義は隅の方は曖昧になっていると言う話。

C の double 型ってどの程度の事が保証されてたっけー。
1未満0より大きい値が表現できる
残念ながら Float って spec に耐えうるほどのことは決まってないよなあ
ともあれrubyだけでそんなCとかアセンブラレベルでの実装の違いまで定義することはできないし、する気もない
まあ spec として書きたい気持ちはわかる

Ruby の Float が IEEE 754 を仮定してないのはなんでなの?
IEEE 754 が実装されてる訳じゃないから
ていうか、他のプラットフォームも一部libmの実装がバグってる
C の double は弱すぎなんだけど、IEEE 754 は逆に強すぎるんだよな
おおむね IEEE 754 っぽいものを実装している―だったらすでに仮定してますね

atanh とか sqrt とかがバグってる例、一部仮定は INFINITY と NAN とか。

いっそ Float を消し去って

やっぱりいっそ Float を消し去って、Rational のリテラル扱いにしてしまえばいいんだ
Floatを消してNArrayを入れました
→わっしょい

1.7.days

rubyspec がというか、rails 関係の人達が本当に欲しいのは
Float じゃなくて Float のリテラルに過ぎない予感がする
1.7.days とか書きたいだけ
かもね
だから、Float#days側でがんばってRationalに変換すればいいんだよな

1.7 になっちゃったものを 17/10 に復元できるかな
Float#rationalize をご所望で
x っていう浮動小数点数の有理化は、±機械イプシロンの開区間に入るどの有理数にしても良いのでその中で最もシ

無理数の発見の歴史 の「連分数展開 - 現代的視点から」にある近似分数の説明が詳しい。

結局、Float#daysは中でrationalize使えば解決するんだっけ

うまくFloat#rationalize(e) の e を指定すればいい気もする

標準入出力の置換え

前とある知り合いの人から
Lisp なら (let ((standard-output out)) e) で標準出力を置き換えられるのに
Ruby では $stdout = out で置き換えられない
Ruby sucks! って言われた事がある
と思ったができてるじゃん
open("foo.txt","w") { |stdout| $stdout = stdout; print "Test.\n" }
print はちゃんと $stdout.write を呼んでる

http://www.ruby-lang.org/ja/man/html/_C1C8A4DFB9FEA4DFCAD1BFF4.html#a.24stdout
{hermit_} 組み込み変数 - Rubyリファレンスマニュアル [text/html; charset=euc-jp]
{mame} 標準入力、出力、エラー出力のリダイレクトを行いたい場合は、 IO#reopen を使用します(1.6 でも同じ)。例えば、
{mame} $stdout = File.open("/tmp/foo", "w")
{mame} は、
{mame} STDOUT.reopen("/tmp/foo", "w")
と書いてはある
{mame} ただし、子プロセスにもリダイレクトの影響を与えたいという要件がないなら $stdout 等への代入で十分です。
これか
なるほど

libcのposとマイナス値

libc とかで pos が負になることってある?
ftell
ないはず
なったらエラーと区別できなくて困るな

Rubyのposとマイナス値

rubyのposはマイナスありですか?
BSD の tty は任意の位置に seek 出来たような気がする

{n0kada} $ ruby -e 'p STDIN.seek(-10, IO::SEEK_CUR); p STDIN.pos'
{n0kada} 0
{n0kada} 2357314
単にdarwinはttyに対するシークの結果がでたらめなのか

Linuxではエラーになった
-e:1:in `seek': Illegal seek - (Errno::ESPIPE)
まあ、まっとうだわな

ふむ。FreeBSD では 0x7fffffffffffffff にしたあと 1byte 書いて pos を呼ぶと EINVAL になるな

NetBSD 4.0.1 では ruby -e 'STDIN.pos = -1;p STDIN.pos' が [BUG] rb_sys_fail() - errno == 0 といって落ちる

[BUG] はいただけないので 1) posのマイナスをrubyレベルで却下、例外上がる 2) posのリード時にエラーが起きても終わらせずに例外上げる の2択な気がする
マイナス値に一つでも有用な使い道があるなら2かな
でも、1が簡単なので、そっちに惹かれている・・
3) errnoをチェックしてみる
ああ、事前にerrno=0とするという作戦か
あんまり好きじゃないけど、ありですね
SEEK_CUR とかを考えると 1) は無理
それはrubyレベルでposはおぼえるべきではない、という暗黙の前提があるように思いますが、これはなぜやってないんでしたっけ?
意図は、いくつかの例外ケースを除きlibcでバッファリングしてよい情報はrubyでもバッファリングしてよいはずで、posってlibcはFILE構造体の中にもってますよね。と

IOのエンコーディング周り

エンコーディングが問題なんだったら、バッファリングと変換のレイヤーでデータを分けたほうがいいんじゃないだろうか
現状ではIOライクなオブジェクトの実装がとてつもなくめんどくさい
変換周りをごっそりコピーしないと無理だし
それは同意
IO::Writable とか IO::Readable とかは立ち消えになっているなぁ
C++みたいに菱形継承にするということ?
意図は似ている
現状のIOって責務が3つあると思っていて
1)write, readシステムコールの発行的な本当のIO、2)バッファリング、3)コード変換 1以外は再実装が必要ないはずである
という議論だと思っているが、あってますか?
そういう感じ

たぶん必要なんだけどむつかしい