2007年06月22日 19:15 [Edit]

perl - no encoding; # whenever possible

camel

うーん、これ、かなり5.8 portersの想定の範囲外の使われ方だったのですね。

Time to ditch encoding.pm: blog.bulknews.net
Perl でソースコードにマルチバイトなリテラルを埋め込む場合には encoding プラグマを使うのが定石でしたが、

元々、encodingプラグマは、JPerlなど、L10Nなperlを発展的に解消させる、あるいは成仏させるためのプラグマ。5.7当初は$^ENCODING直接操作させないためのものでしたが、これを工夫すれば、L10N perlの成仏にも使えるという指摘を私がして、実験的にcharsetというpragma moduleを書いたのですが、5.8のpumpkingであるjhiとの協議の結果、encodingの方に$^ENCODING操作以外の機能がmergeされたというのがその歴史です。

よって、use encoding 'UTF-8';というのは、想定の範囲外だったのです。

そもそも、UTF-8リテラルを使うのであれば、use utf8;で充分なのです。実際私が書くcode sampleも、UTF-8で閉じている場合はEncodeすら使っていません。

きっかけは、RedHat 8だったと思います。これのデフォルトのlocaleがen_EN.UTF-8で、そしてuse encodingで引数を省略した場合、Localeの値がデフォルトになるということが、悲劇を生みました。知らないうちにRH8ではuse encoding 'UTF-8';していたのと同じになってしまったのですね。

本来のencodingプラグマの役割は、過去のソースのための「つなぎ」だったのに、偶然かつあまり幸福とは言えない形で現代も使われているわけです。「このあたりのことをわかってないと、かえって不幸になる可能性がありますよ」というのはencodingのPODにさんざん書いてはいたのですが、しかし立っているものは$^Hでも使ってしまうのがPerl Mongersの悲しい性。

特に問題だったのは、$^ENCODINGが、File Scopeなこと。encodingがLexical Scopeでない原因が、これでした。かといって、$^H{ENCODING}も使えません。なぜそうなのかは

YappoLogs: encoding::sourceをperl5.8系で動かす
このへんの事は体で理解している弾さんに添削されたい><

を参照のこと。

しかしencoding以外にも、lexical pragmaを使いたいという需要はかなりあり、このあたりが5.9のtodoになったのは5.8のrelease時点ぐらいにまで遡れます。それを活用したのが、encode::sourceencoding::stdioというわけです。

しかし、本来あるべき姿は、UTF-8以外の文字列リテラルは極力ソース中には置かず、これらを外部データとして持った上でEncodePerlIOを使って都度変換するべきだ、というのは、5.10になっても変わりません。そんなわけなので、Yappo Hackには感心しつつも、5.8に無理矢理encode::sourceの機能を加えようとするのは、実用面では感心できません。5.10を待つか、5.8におけるベストプラクティス、すなわちencodingフリーなコードを書くかどちらかにした方がよいでしょう。私の推奨は、もちろん後者です。

Dan the Perl 5 Porter


この記事へのトラックバックURL