Ruby 1.9.2.p0 で Array を print すると日本語が化ける

仕様のようでもあるし、バグのようでもある状態に遭遇したので書いてみる。

# -*- encoding: SJIS -*-

arr = []
f = open( "sample.dat", "r:SJIS" )
while buf = f.gets
	arr.push $1 if buf =~ /(.+)$/
end
f.close

$\ = "\n"
$, = ","

print "1 ", arr
print "2 ", arr.join
print "3 ", arr.join($,)

p arr

こんなプログラムを Windows のメモ帳で書いて sample.rb としておき、

あいうえお
あきくけこ
あしすせそ
たちつてと
なにぬねの

こんなファイルをメモ帳で書いて sample.dat という名前でセーブしといて、Windows7 + ruby-1.9.2-p0-x64-mswin64_80 で sample.rb を実行すると、

> ruby sample1.rb
1 ,["\x{82A2}\x{82A4}\x{82A6}\x{82A8}", "\x{82AB}\x{82AD}\x{82AF}\x{82B1}", "\x{82B5}\x{82B7}\x{82B9}\x{82BB}"]
2 ,いうえお,きくけこ,しすせそ
3 ,いうえお,きくけこ,しすせそ
["\x{82A2}\x{82A4}\x{82A6}\x{82A8}", "\x{82AB}\x{82AD}\x{82AF}\x{82B1}", "\x{82B5}\x{82B7}\x{82B9}\x{82BB}"]

こんなふうに化けてしまう。最後の p が化けるのはまだしも、1. が化ける理由がよくわからない。プログラミング言語 Ruby リファレンスマニュアル の print を見ると、

文字列以外のオブジェクトが引数として与えられた場合には、 当該オブジェクトを to_s メソッドにより文字列に変換 してから出力します。

とあって、プログラミング言語 Ruby リファレンスマニュアル の to_s を見ると、

self.join($,) と同じです。

とあるから、

print arr
print arr.join

この二つの print の結果は同じになるはずなのにならない。この症状に気がつくのにかなり時間かかった。p138 では直っているのかもしれないけどわからない。ちなみに arr.to_s でも化ける。ということは、to_s は join と等価じゃないってことだよね。もうちょっと調べてみるか。

うーん、http://doc.ruby-lang.org/ja/1.9.2/method/Array/i/join.htmlを見ても 1.9.2 で Array の仕様が変わったとも書いてないから、やっぱりバグ?
とかいってたら,なんかある暇っぽい人から,

encoding:Windows-31J にして r:SJIS を r だけにしたらいいんじゃね?

という指摘があった.試してみたら確かに化けなくなった.encoding:cp932 でもいいらしい.

SJIS という表記がよくないという話はあるだろうけど,それにしても coding:SJISWindows-31J が読めて途中の処理はできているのに,print arr と print arr.join の処理結果だけ異なるというのはなぞ.