作者: 藤岡和夫
日時: 2008/6/29(09:46)
On Sun, 29 Jun 2008 01:06:47 +0900
"Bruce." <kbk@...> さんwrote:

 長文のコメントありがとうございます。

> use encoding は失敗例とみなしていいような状況ですし、spamフィルタを見れば
> 想像がつくように文字コードに関しても100%正しく判定し、誤判定がありえない
> 手法なんてありません。
>
> ある種の制約条件。たとえばuse なり require で取り込むモジュールにおいても
> まったく同じ条件で動作することを使う側が保証するとか、あるいはモジュールを
> 一切使わないというような条件をおいていいのなら、jperl的なものがつくれる
> かもしれません。しかしながらその場合においても、入力される文字の
> エンコーディングは複数存在することが当然のことで、決め打ちできる状況のほうが
> むしろまれなことでしょう。
> 
> であれば、処理系の作り手としては今のようなやり方になってしまうのは
> 「汎用」のものであればやむを得ない判断であろうと考えています。
> 
> 〜すべきとおっしゃるのは結構ですが、漠然と望んでいたってそれがかなうことは
> ないと思います。Larryを筆頭としたコアチーム、は無理としても名の知れた
> 日本人Perlハッカーにでも訴えてみたらいかがですか。

 私が「あるべき」と考えていることは、既に考えられていることだと思います
が、Perl 6でどのようになっていくのかに期待しています。Perl 5で作り直すこ
とは現実的でないでしょう。Perl 6だから簡単ということでもないでしょうが、
よりよいものになるだろうと思っています。

> 
> > 1. 文字列はUTF-8を使うことが前提。
> > 2. 入力時にUTF-8フラグを必ず立てる。
> > 3. UTF-8フラグを立てた状態で文字列処理を行う。
> > 4. 出力時はUTF-8フラグを降ろす。
> > 
> > このフラグを立てたり、降ろしたりというのが、どうもスマートには思えないん
> > ですね。しかし、ないものねだりをしても仕方がないので、フラグを立てたり、
> > 降ろしたりに何を使うかを考えました。
> 
> encode/decode をきちんとやっていれば、フラグがどうこうなんてことは
> ほとんどありません。

 encode/decodeというのは具体的にどの操作を指されているのですか。utf8プ
ラグマですか、Encodeモジュールの話ですか。これらは同じことをやるのだろう
か。

> perluniadvice - daily dayflower
> "抄訳 perluniadvice
> 
> Perl 付属のドキュメント perlunitut はもう読んだ?もしまだなら,そこから読み始めること :)
> 
>     * perlunitut - perldoc.perl.org
>     * perlunifaq - perldoc.perl.org

 Unicode関係のPerlドキュメントはすべて目を通していますが、体系的に頭に
入りにくいのですね。いろいろなことが有るので複雑だという印象を否めない。

 昨年からのTSNETでのでびさんや林さんの関連のスクリプトに触ってきた経験
の御蔭もあって、今回、いろいろ具体的に書いてみたり、Webの情報を読んでい
ると少しずつ頭の中が整理できてきました。僕は日常的にスクリプトを書いてい
るわけではないので、進歩が極めて遅いのです^^;)

 よく考えると当たり前のことなんだなあ。それぞれの場面でフラグを立てたり、
降ろしたりする必要がある。それぞれの場面とは、

1. スクリプト中に書いてあるUTF-8テキストデータ。
2. 標準入出力
3. ファイル入出力
4. モジュール入出力(データベース入出力などを含む)
5. 既に開いている入出力

 そう考えると、自在に対応できそうだと考えたわけです。

> 以下にわたし(http://juerd.nl/)からのアドバイスの要約を挙げる。perlunitut には記述しなかった内容も含んでいる。
> 
>     * もしあなたが古い Perl を使っているのなら,最新版にアップグレードしよう
>     * もしあなたが古い CPAN モジュールを使っているのなら,最新版にアップグレードしよう
>     * 「外界」からやってくるデータはすべて decode() しよう
>     * 「外界」へ出力するデータはすべて encode() しよう
>     * 「テキスト文字列」と「バイト列」をあなたのプログラムの中で完全に分離しよう
>     * ある「string」が「テキスト文字列」なのか「バイト列」なのか Perl は判断できない,ということを認識しよう
>     * 「Unicode 文字列」とは「Unicode」文字列であって「UTF-8」文字列ではない,ということを認識しよう(!!)
>     * UTF8 flag なんて存在しないかのように振る舞え
>     * UTF8 flag を明示的にいじるな(on したり off したり)
>     * UTF8 flag の状態を取得するな(Encode::is_utf8(), utf8::is_utf8())
>     * 「string」に UTF8 flag が立っている場合にそれが「テキスト文字列」であるとは言えるけれど,逆は必ずしも成り立たない
> ことを認識しよう
>     * もしあなたが「string」を utf8::downgrade() しなきゃいけないとしたら,それはたいていそれ以前の処理が間違っている
>     * ソースコードが UTF-8 エンコーディングで書かれているときだけ use utf8; を使え
>     * use bytes; を使うな
>     * bytes:: ネームスペースの関数を使うな
>     * 正規表現で \C を使うな
>     * use encoding; を使うな
>     * pack() で「バイト列」を生成する場合,「C*」テンプレートを使え
>     * 「テキスト文字列」を unpack() するとき「U」テンプレート以外を使うな
>     * 「バイト列」を unpack() するとき「U」テンプレートを使うな
>     * pack() / unpack() で「U」テンプレートと「非 U」テンプレートを混ぜて使うな
>     * pack() で「U0」や「C0」テンプレートを使うな
>     * lc() / lcfirst() / uc() / ucfirst() する前に utf8::upgrade() しよう
>     * 大文字小文字を区別しないマッチングをする前に utf8::upgrade() しよう
>     * \w や \s などのキャラクタクラスをマッチングで使う場合,その前に utf8::upgrade() しよう
> 
> 内部のごちゃごちゃ(UTF8 flag など)を直接さわらないと解決できないことがあるかもしれない。Perl の Unicode サポートと相性
> が悪いモジュールを使ったり,実装が間違っているモジュールを使ったりしなきゃいけない時とか。ということで,以上にあげた項目
> は大まかな原則である。"
> http://d.hatena.ne.jp/dayflower/20080625/1214374293
> 
> perlunitut 和訳 - Perl Unicode Tutorial
> http://www.r-definition.com/program/perl/perlunitut.htm
> 
> > $chars = "い,ろ,は,に,ほ,へ,と,ち,り,ぬ,る,を,わ,か,よ,た,れ,そ,つ,ね,な,ら,む,う,ゐ,の,お,く,や,ま,け,ふ,こ,え,て,あ,さ,き,ゆ,め,み,し,ゑ,ひ,も,せ,す,ん";
> > @tbl = split(",", Unicode::Japanese->new($chars)->getu);
> 
> 元のawk版はまあ仕方ないにしてもなんでわざわざカンマ区切りの文字列を使うのでしょうか?

 これは、単に機械的に置き換えただけですね。考えていないです(^^;)意図ど
おり動作すればOK。Ruby版も変えることは可能ですね。splitの部分。

tbl = "いろはにほへとちりぬるをわかよたれそつねならむうゐのおくやまけふこえてあさきゆめみしゑひもせすん".split(//)

> #!/usr/bin/perl
> use strict;
> use warnings;
> use Fatal qw(:void open close);
> use feature ':5.10';
> 
> use utf8;
> binmode STDOUT, ':encoding(cp932)';

 ShiftJIS出力ですね。私の書いているUTF-8出力スクリプトはWindowsでは、Cygwin
を入れてck/ckstartup.jsを使うか、Aprotool TM Editorのコンソールを使わな
いと文字化けします。

> 
> my @chartbl1 = qw(い ろ は に ほ へ と ち り ぬ る を わ か よ た れ そ つ ね な ら む);

 これは思いつきませんでした^^)

> my @chartbl2 = split q{}, qw(いろはにほへとちりぬるをわかよたれそつねならむ);
> 
> say join ':', @chartbl1;
> say join ':', @chartbl2;

 sayも便利ですね。

> 
> ------
> い:ろ:は:に:ほ:へ:と:ち:り:ぬ:る:を:わ:か:よ:た:れ:そ:つ:ね:な:ら:む
> い:ろ:は:に:ほ:へ:と:ち:り:ぬ:る:を:わ:か:よ:た:れ:そ:つ:ね:な:ら:む
> 
> 

藤岡 和夫
kazuf@...
日曜プログラマのひとりごと http://homepage1.nifty.com/kazuf/renewal.html