丁稚な日々

Rubyで遊んだ日々の記録。あくまで著者視点の私的な記録なので、正確さを求めないように。
Rubyと関係ない話題にはその旨注記しているはず。なので、一見関係無いように見える話題もどこかで関係あるのかもしれません。または、注記の書き忘れかもしれません...

[直前] [最新] [直後] [Top]

Feb.3,2009 (Tue)

Revision: 1.1 (Feb.03,2009 11:49)

Feb.5,2009 (Thu)

Revision: 1.2 (Feb.06,2009 14:56)

『プログラミング言語Ruby』刊行記念トークセッション@大阪

_ 表題のイベント(と、付随して開催されたokkezさんが幹事の懇親会)に行ってきた。
最近はイベント系にはまったく参加してないので、たぶんRuby会議以来(松江でやったOSCにちらっと顔を出したりはしたけど)。

_ 直前にささださんが嫌なバグを見つけたのをつついていたせいで、会場に着くのがギリギリになってしまった。

_ トークセッションの内容は、本の背景とか各章の内容とかを紹介しつつ若干の脱線を交えるという感じで、ふーんへーほー、といったところ。
それなりにうまく進んだけど、どこまで打ち合わせてやってんのかなあ、と思った。
やや時間を余して終わって「(1) 質疑応答をする」「(2) 1.9の新機能について聞く」「((3) もう終わって帰る」の選択肢が聴衆に与えられたんだけど、(3)を選んだのはおいらだけだったので(2)になってしまった。トイレに行きたかったんだよぅ。
なお1.9の新機能の紹介はm17nだけで終わった :)

_ 終了後はサイン会。
たぶん原著を持ち込んでサインしてもらったのはおいらだけだろう(アホだ)。
いやもちろん日本語版もサインしてもらったよ!

_ その後トイレに行って戻ってきたら懇親会へ行くはずの集団が既に消えていて動揺したのは内緒だ。

_ 懇親会ではいつものようにまあ適当に雑談。
いつものようにrubyに対するねじれた毒を吐いた気がするが、愛だよ、愛。
西山さんから「$SAFE=1requireが失敗する件が直らないまま1.9.1が出た」という話を聞かされて凍りつく。
あれはshow stopperじゃなかったのかー! てっきり誰かが直したから出たものとばかり...

Feb.9,2009 (Mon)

Revision: 1.3 (Feb.09,2009 21:15)

[mswin] locale

_ そういやRubyist Magazine 0025号が出てるという話を書いてなかった。
ま、こんなところに書かなくてもみんなとっくに読んだよね!
で、成瀬さんが書いた「Ruby M17N の設計と実装」は、Ruby M17Nについてその背景を説明した、現時点では唯一無二のまとまった資料だと思われる。
この中で、mswin版に関して留意すべき点をすこし説明しておこう。

_ まず、Windowsでプログラムを書く場合、内部では4つのエンコーディングが使用されることを考慮する必要がある(Win9xでは若干事情が異なるが本稿では考慮しない)。
具体的には、コンソールコードページ、ANSIコードページ、OEMコードページ、システムネイティブエンコーディングである。

_ コンソールコードページはWin32コンソールで使用されるもので、具体的には「コマンド プロンプト」なんかで使われる。
これはchcpコマンドで各コンソールごとに切り替えが可能。

_ ANSIコードページはWin32 APIのANSIバージョンと呼ばれるものでほとんどの場合使用されるもの。
これはユーザ単位でシステムワイドに設定できる(ちなみにこれを変更するAPIは存在しない)。

_ OEMコードページはWin32 APIのANSIバージョンのうちファイルエントリ絡みのもので使用されることがある。「ことがある」という言い方をするのは、これらのAPIでもANSIコードページを使うかOEMコードページを使うか切り替えることが可能なため。
なんでファイルエントリ絡みでだけOEMコードページを使ったりするのかという点については、「歴史的事情」としか言いようがない。
まあ、そんなこと言ったらANSIバージョンAPIの存在自体が歴史的事情だが。

_ システムネイティブエンコーディングというのは今私が命名したものなので公式な名前ではないが、Windowsが内部的に使う。
単に「Unicode」として紹介されることが多いが、現代ではUTF-16LEが使われている(古いNTなどだといわゆるUCS-2)。
これはWin32 APIのWide文字バージョンで使われる。また、ANSIバージョンのAPIを呼び出しても、システム内部では基本的にはシステムネイティブエンコーディングに変換した上で扱われる。
ファイルエントリに対しても、VFATやFAT32、NTFSなど、Windowsのネイティブファイルシステムにおいては、ファイルの真の名前はシステムネイティブエンコーディングで格納される。

_ 現在のruby実装でこれらがどう現れるかというと、コンソールコードページに対応するエンコーディングについてはEncoding.find("locale")で取得できる。
また、rubyレベルでそのエンコーディング名を単純に取得する方法は提供されていないが、ファイルシステムエンコーディングという形でANSIコードページまたはOEMコードページが取得できる(*1)
残りの二つ、つまりANSIバージョンAPI呼び出しに使用すべきエンコーディング、および、システムネイティブエンコーディングについては、ruby実装中には表立っては登場しない。
これはなぜかというと、前者については、ユーザが自前でANSIバージョンAPI呼び出しを行わない限り必要ではなく、またそれを行いたい場合はその際に自分で取得可能なはずだからである。
後者についても、Wide文字バージョンAPI呼び出しを行わない限り云々なのだが、それに加えて、どうせUTF-16LE固定なんだから考えるまでもない、ということもある。

_ さて、mswin版rubyでは、なぜEncoding.find("locale")で取得できるエンコーディングがコンソールコードページのものなのか。
実は、Ruby M17Nの現状の実装における「locale」というのは「デフォルトでEncoding.default_externalに設定されるエンコーディング」である。
基本的にIOのエンコーディングはスクリプト作者が指定すべきものである、というのがRuby M17Nのスタンスであるから、Encoding.default_externalは標準でオープン済みのIOの初期外部エンコーディングというのが主たる意味になる。
「標準でオープン済みのIO」というのは要するに$stdin$stdout$stderrである。
これらは(リダイレクトが絡まない限りは)当然コンソールに結びついているので、Encoding.default_externalはコンソールコードページのエンコーディングになるのが妥当である(UTF-16LEになるという選択もありえるが、1.8までとのスクリプト互換性を考慮すると却下される)。

_ しかし、実際にrubyレベルで"locale"という名前でエンコーディングが取得できてしまうと、これをEncoding.default_externalのデフォルト値、という意味を超えて使う人が現れるのは当然だろう。
長期的にはmswin版rubyでもこれをANSIコードページのエンコーディングを指すようにする、などの変更は必要かもしれない。

_ UNIX類だけ考えると、システムコール呼び出しもファイルエントリもtty入出力も、プロセス単位で決定される唯一のエンコーディング(つまり環境変数LANGで決定される「locale」)を使えばいいので話は簡単だ。
Mac OS Xにおいても事情はほぼ同様で、ファイルエントリのエンコーディングのみ別途決定可能であればよい。
しかし、Windowsだとコンソール入出力(tty入出力に相当)もWin32 API呼び出し(システムコール呼び出しに相当)のエンコーディングと分離する必要があるわけである。
将来のRubyでは、この部分をRuby M17Nの言う「locale」として定義する必要があるのだろう。

付記

(*1) ファイルシステムエンコーディングという形でANSIコードページまたはOEMコードページが取得できる
実は1.9.1p0では私のせいで必ずOEMコードページになる。
将来のリリース(1.9.2なり1.9.1のパッチリリースなり)では修正される予定。


被捕捉アンテナ類
[Ant] [Antenna-Julia] [Rabbit's Antenna] [Ruby hotlinks]