なぜ File.read() でなくて IO.read() なのか? なぜ File.read() はあって File.write() はないのか?

Ruby 1.9.1 仕様変更締め切りを記念して、Ruby で前々から疑問に思ってたことを書いてみる。

  • (1) IO.read() は、なぜ IO.read() であって File.read() でないのか。引数に filename を取るんだから、filename に関係ない IO より、関係のある File のほうに定義すべきだったのではないか。
  • (2) IO.read() はあるのに、なぜ IO.write() がないのか。PHP にだって file_get_contents() と file_put_contents() があるというのに、Ruby で IO.write() がないというのは対称性に欠ける。

comp.lang.rubyで聞いてみたけど、あんまり納得のいく回答がなかった。

  • IO.read() じゃなくて File.read() と書けるよ
    • → そんなことはわかってるし、答えになってない
  • File.read() を自分で定義したライブラリを用意すればいい
    • → これも答えになってない
  • File.write() は File.read() より dangerous だから用意されてないのさ
    • → File.unlink() はもっと危険なのに用意されているぞ
  • IO.write() は、ファイルの先頭から書くのか後ろに追加するのかとか、バイナリモードにするかどうかなど、オプションがたくさんあって複雑になるから用意されていない
    • → IO.read() だって、後ろの N バイトだけを読むとか先頭の N バイトを読み飛ばすとか考えられるし、バイナリモードだってある。
  • File オブジェクトには << 演算子が使えるぞ
    • File.open(filename, 'w'){|f| f << str } を使えといってるなら、これも答えになってない


なんかこう、いろいろ理由をこじつけているけど、どれも納得できる理由にはほど遠い。つうかさ、知らないなら知らないって答えればいいのに、なんでこんなに変なこじつけを考えるんだろうね。


・・・と思っていたら、なんとまつもとさんが降臨!

I have questions about IO and File class.
Why is IO.read(filename) defined?
IMO, File.read() is more natural than IO.read() because
IO class is not related to filename, I think.

No big reason. Historically IO works on files, i.e. IO.open(path),
so that it was natural to provide these methods in IO too.

特に理由はないらしい。「IO works on files, i.e. IO.open(path)」の箇所はいまいち意味がわからないけど。

でもなあ、File#open(path) は filename を引数にとるけど、IO#open(fd) は file descriptor を引数にとるんだよな。
そう考えると、IO.open() が file descriptor ではなく filename を引数にとるのは違和感がある。

Is there any reason that IO.write() (or File.write()) is not
provided?
I have to define File.write() for each project...
It is easy to define File.write() but I hope it is provided by Ruby.

For File.read(), when you want to specify file mode, you can just say:
File.read(path, "rb")
For File.write(), it is more likely to be:
File.write(path, str, "wb")
which makes me feel weird. In 1.9, we can write
File.write(path, str, mode: "wb")
which I feel slightly better.
matz.

これは最初、Ruby1.9 では File.write(path, str, mode: "wb") というのが用意されるのか! ヤッター! ・・・と読んでしまったが、そうではなかった。
やっぱり Ruby1.9 でも File.write() は用意されないみたいだ。


Symbol#to_proc は導入されるくせに File.write() が用意されないなんて、なんか納得がいかない。