SSブログ

[Perl] Perl の内部形式に関する調査 [Perl]

【2008.03.13】
Perl の内部形式は Unicode で保持しているようだ、と書きましたが誤りでした。すみません。
dayflower さんに指摘して貰いました。ありがとうございます。

perldoc に書いてあるように内部形式はやはり UTF-X で、(Perl 5.10 では特に) Perl が自動的にいろいろな処理をしているため内部形式は表に出てこないようになっています。
Perl の Unicode 文字列を使い始めた人が引っかかるかもしれない (というか自分が引っかかった部分) について書いておきます。

1. 文字は \x{XXXX} という表記で表せるが、\x{00XX} は \xXX と等しい

これは、まず最初に引っかかる部分だと思います。Perl 5.8 (5.6?) 以降では \x{XXXX} という表記で文字を表すことができます。XXXX は Unicode のコードポイント (16 進表記) です。しかし、0x100 より小さい値を XXXX に指定した場合は、\xXX というバイナリデータと同じものを表すことになります。つまり、\x{004A} は \x4A に等しいです。
このとき utf8 フラグは立ちません。また、chr 関数も同様で、chr 関数の引数が 0x100 未満の場合は Unicode 文字ではなくバイナリ構造を返します。
ですが、おそらくそれで何も問題なくプログラムを作成していくことが出来ます。このため、コードポイントが 0x100 未満の文字は utf8 フラグが付いていなくても付いていても内部的には同じだ、と考えてしまうかもしれません。ですが実際には内部では違うバイナリデータで (U+0080 ~ U+00FF に関しては)、Perl が上手く処理しているために問題なくプログラムは動作します。

2. pack / unpack 関数の動作

Unicode 文字の導入に伴い、pack / unpack 関数は変更されました。
以前までのように、「文字」に対して unpack することはすべきではありません。文字に関する pack / unpack のテンプレートは 'U' と 'W' ぐらいだと思います。
pack('U', 0x4A) のように pack することで、そのコードポイントが表す文字になります。逆に unpack すると、文字のコードポイントがわかります。'W' は 0x100 以上に関しては、'U' と同様の動作ですが、0xFF 未満に関しては 'C' と同様の動作をします。(つまり chr / ord 関数と同じ)

また、pack / unpack 関数には Perl 5.10 から U0 スイッチと C0 スイッチが導入されました。よって Perl 5.8 と 5.10 で動作が異なります。ここで引っかかる人も居るのではないかと思います。
詳しくは perldoc を参照してください。

3. その他いろいろ

他にも、Unicode 文字を扱っていると、思った以上に Perl が自動的にいろいろと処理を行うため、それが逆に落とし穴になってしまうこともあると思います。
例えば、1. で述べた U+0080 ~ U+00FF の文字と \x80 ~ \xFF のバイナリデータが同じように見える、という問題。
これは、Perl が互換性などのために行っていることで、この動作について知っていると何かと便利だと思います。しかしこの動作を知らなければいろいろ勘違いすることにもなりかねません。(まさに自分がそれです)
この動作については dayflower さんがまとめているのでご覧ください。
UTF8 フラグあれこれ - daily dayflower
また、私も拙いながらまとめてみました。
Perl の内部形式についての考察


【元の記事】 誤りです
Perl の Unicode 対応について で Perl の内部形式(あっちでは内部表象という表現をした)について触れましたが、さらに細かい部分について考えがまとまったので書いておきます。 ここではまとめのみを述べます。詳しい内容は Perl の内部形式に関する考察 に書きましたので、参照してください。 まず、Perl が扱うデータには、バイナリ列 (binary strings) と文字列 (text strings) の 2 種類があります。 文字列は「文字」を「文字」として扱うのですが、コンピュータなので内部的にはエンコードしてデータを保持しています。その内部的なエンコードを内部形式 (internal format) と言い、UTF-8 エンコードとして扱われる、と一般的に言われています。が、それは正しくありません。 内部形式は、バイナリ構造で Unicode のコードポイントを保持しているようです。 なぜ、一般的に内部的に UTF-8 エンコードで扱っていると言われているかというと、おそらく「文字」を unpack すると UTF-8 のコードがでてくるから、だと思うのですが、それは Perl 5.8 では自動的に UTF-8 エンコードに変換されているからで、決して内部形式が UTF-8 エンコードなわけではありません。 Perl 5.10 では pack / unpack の仕様が変わっていて、unpack すると UTF-8 エンコードされた値ではなく内部形式の値を直接扱うことになります。 perldoc とかを見ても内部形式は UTF-8 ?みたいなことを書いてるのであんまり自信はないんですが。。 まあ詳しいことは Perl の内部形式に関する考察 に書いてあるので気になった方は見てください。何か問題点があればご指摘ください。 +++ Perl 5.10 では、Perl 自身があまり utf8 フラグを気にしてないよね・・・。

nice!(0)  コメント(0)  トラックバック(2) 
共通テーマ:パソコン・インターネット

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 2

[Firefox / Add-on] ..[Perl] 続 UTF-8 から Sh.. ブログトップ

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。