From: Tanaka Akira Date: 2008-01-14T00:33:41+09:00 Subject: [ruby-dev:33080] Re: Binary String In article <20080112.100830.112615025.nagai@ai.kyutech.ac.jp>, Hidetoshi NAGAI writes: > 自分自身でも何が何だか分からなくなってきたので, > 質問を一旦整理してみます. そういうときはやはり具体的な問題に立ち帰るのがいいんじゃない でしょうか。問題の具体例を示してみるのはどうでしょう? > まず最初に, > > * encoding が未定義ならば,デフォルトを使って救済してあげたいと > 考えるのは「悪」か? かなり筋が悪いと思います。 ここでいうデフォルトというのは要するに locale で使われるエン コーディングですよね。つまり、テキストで知らない名前のエンコー ディングだったらそれは locale に従っているという推測を行うと いうわけです。 これは、特定の locale に従って動いているシステムの内部で生成 されたデータであれば、正しい推測となります。 しかし、ひとつの locale ですべてが処理される、というのは幻想 であり、ひとつのシステム内で複数の locale が同時に扱われると いうことはよくありますし、さらには、外部のシステムが同じ locale であるとはまったく保証できません。 外部のシステムとの通信で良くあるのは MIME でしょう。たとえば、 メールや HTTP です。受け取ったデータの charset パラメータに 知らない名前が書いてあった時、永井さんのいう、文字列の encoding が未定義という状態になります。 (encoding は定義すると GC されずメモリを確保しっぱなしになる ため、その名前の dummy encoding は定義しないこととします) この場合、locale に従っているという推測は正しくありません。 一般に locale に従うという推測は正しいとは限りませんから、 そのような推測を行うのはなるべく状況証拠があるときに限定すべ きです。状況証拠というのは、たとえば、端末から読み込んだデー タである、とかです。それだって正しいとは限りませんが、MIME でどこかから来たデータが locale に従うというよりはずいぶんと ありそうなことだと思います。このような状況証拠はデータを読み 込むところが一番良く知っていて、処理が進むとどんどん消えてい きます。 tk のような、データがどこから来たのかわからない部分で推測を 行うのは避けたほうがいいのではないでしょうか。 > Ruby 1.8 の Ruby/Tk では救済を図る方針でやってました. > しかし Ruby 1.9 では,救済を考えること自体が「悪」であり > 「小さな親切,大きなお世話」であるというのであれば, > どうしようもありません. 外界との情報のやりとりの大部分に文字の情報がついているように ならない限り、救済自体は必要でしょう。しかし、その救済は適切 な救済ができそうなところで行うべきです。そして、それができそ うなところは、データが読み込まれるところであり、tk にデータ を送り込むところは違うのではないかと思います。 さて、tcl 8.5.0 の library/encoding/ をいくらか眺めてみまし た。間違っていたら指摘してください。 ASCII 互換で単一バイトなエンコーディングは ASCII-8BIT の replica として定義すればそれなりに動きます。 この範疇にあるのは (Ruby や Oniguruma に定義があるものも含め て) 以下の通りです。 ascii, cp437, cp737, cp775, cp850, cp852, cp855, cp857, cp860, cp861, cp862, cp863, cp864, cp865, cp866, cp869, cp874, cp1250, cp1251, cp1252, cp1253, cp1254, cp1255, cp1256, cp1257, cp1258, gb1988, iso8859-1, iso8859-2, iso8859-3, iso8859-4, iso8859-5, iso8859-6, iso8859-7, iso8859-8, iso8859-9, iso8859-10, iso8859-13, iso8859-14, iso8859-15, iso8859-16, jis0201, koi8-r, koi8-u, macCentEuro, macCroatian, macCyrillic, macGreek, macIceland, macJapan, macRoman, macRomania, macThai, macTurkish, macUkraine, tis-620 ASCII 互換なマルチバイトエンコーディングは以下の通りです。 この中で、cp936 (GBK) と cp949 (EUC-KR の MS 拡張) は Oniguruma にもなくて、定義が必要そうです。 cp932, cp936, cp949, cp950, euc-cn, euc-jp, euc-kr, big5, gb2312, shiftjis マルチバイトな文字セットをそのまま扱う、ASCII 互換でないのは 以下の通りです。 gb12345, gb2312-raw, jis0208, jis0212, ksc5601 ASCII 互換でない単一バイトなエンコーディングは以下の通りです。 ebcdic, dingbats, macDingbats, symbol stateful なエンコーディングは以下の通りです。 iso2022-jp, iso2022-kr, iso2022 こうやって分類してみると、locale のエンコーディングになりそ うなのは ASCII 互換なものと ebcdic だけに見えます。 マルチバイトな文字セットそのままのもの (jis0208 とか) は portable character set が 1バイトで表現できないといけないと いう POSIX の規約に反します。 dingbats などの記号類は portable character set を表現できず、 これも POSIX に反します。 stateful なのは POSIX 的にはいちおう許されているような気がす るのですが、実装はありましたっけ? まぁ、少なくとも実際によ く使われているようには思えません。 ここで Ruby は EBCDIC を扱わないので ebcdic はやめておくとす れば、残りの中で replica で済まないものは cp936 と cp949 だ けではないでしょうか。 難しい救済に挑戦するよりは、定義しちゃったほうが、tk 以外で も幸せになれますし、いいのではないかと思います。 > * 未定義と定義済とは区別できるべきではないのか? さて。 区別が可能だとして、区別するとどのくらい嬉しいことがあって、 どのくらい厄介なことがあるのか、という問題になります。 tk で嬉しいことがあるというのはそうなんでしょう。 私の懸念は区別する手間です。文字列を生成するときにどちらにす るか、また、正規表現とどうマッチさせるかといった操作など、tk にたどり着くまでに文字列に対して扱われる処理にどのような手間 が増えるかという点に懸念を持っています。 たとえば、文字列を生成するときに、それが tk にたどりつくかど うかもわからないのに、ちゃんとどちらにすべきなのか判断できる のか、とか。 いまのところ大変になるという確信があるわけではないんですが。 でも、もともと tk の API でバイナリを要求するかテキストを要 求するかの情報が欠けているというところから問題が発生している ので、情報を提供するのは tk の近くのほうが適切なのではないか という気はしています。 > 「binary の導入を」という希望は, > 未定義と定義済との区別がなされていないように見える現状に対し, > せめて「(未定義or定義済)と定義済」の区別ができるようにしてほしい > というものです. > > ですので,例えば未定義 == dummy encoding であり, > それによって「未定義と定義済」の区別ができるのであれば > binary == ASCII-8BIT でも何ら不満はありません. 文字列を受け取る側としては区別できるようにしてほしいのでしょ うが、文字列を生成する側はどうでしょうか。区別して生成し分け るのは簡単だと思いますか? -- [田中 哲][たなか あきら][Tanaka Akira]