作者: Bruce.
日時: 2008/6/29(01:06)
Bruce.です。

藤岡和夫 さんは書きました (2008/06/28 18:48):

>> あまり複雑なことをしないのなら
>>
>> ・入力は必ず decode する
>> ・文字列操作は必ずフラグ付きの文字に対して行う
>> ・出力は必ず encode する
>>
>> などいくつかの縛りをつけてやればそれほど難しい話でもないと思いますが
>> どんなもんでしょうか。
> 
>  なるほど、そうですね。実は、それはスクリプティング言語側の仕事であるべ
> きというのが私の意見ですけどね。入出力の作業が増えたのが気に入らない。も
> ちろん、バイト列として取り扱いたい場合がありうるのかもしれませんが、むし
> ろそちらを例外的な操作としたほうがわかりやすい。


use encoding は失敗例とみなしていいような状況ですし、spamフィルタを見れば
想像がつくように文字コードに関しても100%正しく判定し、誤判定がありえない
手法なんてありません。

ある種の制約条件。たとえばuse なり require で取り込むモジュールにおいても
まったく同じ条件で動作することを使う側が保証するとか、あるいはモジュールを
一切使わないというような条件をおいていいのなら、jperl的なものがつくれる
かもしれません。しかしながらその場合においても、入力される文字の
エンコーディングは複数存在することが当然のことで、決め打ちできる状況のほうが
むしろまれなことでしょう。

であれば、処理系の作り手としては今のようなやり方になってしまうのは
「汎用」のものであればやむを得ない判断であろうと考えています。

〜すべきとおっしゃるのは結構ですが、漠然と望んでいたってそれがかなうことは
ないと思います。Larryを筆頭としたコアチーム、は無理としても名の知れた
日本人Perlハッカーにでも訴えてみたらいかがですか。


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

encode/decode をきちんとやっていれば、フラグがどうこうなんてことは
ほとんどありません。


perluniadvice - daily dayflower
"抄訳 perluniadvice

Perl 付属のドキュメント perlunitut はもう読んだ?もしまだなら,そこから読み始めること :)

    * perlunitut - perldoc.perl.org
    * perlunifaq - perldoc.perl.org

以下にわたし(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版はまあ仕方ないにしてもなんでわざわざカンマ区切りの文字列を使うのでしょうか?


#!/usr/bin/perl
use strict;
use warnings;
use Fatal qw(:void open close);
use feature ':5.10';

use utf8;
binmode STDOUT, ':encoding(cp932)';

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

say join ':', @chartbl1;
say join ':', @chartbl2;

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