これはMoritz Lenz氏のWebサイトPerlgeek.deで公開されているブログ記事"Perl 5 to 6" Lesson 17 - Unicodeの日本語訳です。
原文はCreative Commons Attribution 3.0 Germanyに基づいて公開されています。
本エントリにはCreative Commons Attribution 3.0 Unportedを適用します。
Original text: Copyright© 2008-2010 Moritz Lenz
Japanese translation: Copyright© 2011 SATOH Koichi
NAME
"Perl 5 to 6" Lesson 17 - Unicode
SYNOPSIS
(なし)
DESCRIPTION
Perl5のUnicodeモデルは大きな弱点に悩んでいました: バイナリとテキストデータに同じ型を使っていたのです。
プログラムがネットワークソケットから512バイト読み込んだとすると、それは当然バイト列になります。しかしそれに対して(Perl5で)uc
を呼ぶとテキストとして扱われます。
推奨されている方法は最初にバイト列をデコードすることですが、サブルーチンがそれを引数として受け取る段階では、それがエンコードされているのかどうか、つまりblobとして扱うべきかテキストとして扱うべきか確実に判断することは不可能です。
一方、Perl6は単なるバイトのコレクションであるBuf
型を提供します。またStr
は論理的な文字のコレクションです。
論理的な文字という用語にはいささか説明が必要です。正確に言うと、Str
は様々な水準の見方ができるオブジェクトです: Byte
、CodePoint
(Unicodeコンソーシアムが番号を割り当てたものすべて)、Grapheme
(書記素; 文字として目に見えるもの)、CharLingua
(言語定義文字)。
例えば16進数表記で61 cc 80
は(当然)3バイトのバイト列を構成します。しかしこれは2つのコードポイントLATIN SMALL LETTER A
(U+0041)とCOMBINING GRAVE ACCENT
(U+0300)、あるいは1つの書記素(ブログシステムないしあなたのブラウザが文字を殺してなければ、à
のように見えます)を表しているものと見ることもできます。
したがって文字列の長さを単純に調べることはできず、特定の見方に拠る長さを調べる必要があります:
$str.bytes;
$str.codes;
$str.graphs;
chars
メソッドもあり、これは現在のUnicode水準(use byte
のようなプラグマで指定でき、デフォルトは書記素)における長さを返します。
Perl5ではしばしば間違ってバイト列を文字列に連結してしまう問題が起きます。 Perl6でそのような問題に悩んだときは、文字列連結演算子をオーバーロードして簡単に問題が発生した位置を特定できます:
sub GLOBAL::infix:<~> is deep (Str $a, Buf $b)|(Buf $b, Str $a) {
die "Can't concatenate text string «"
~ $a.encode("UTF-8")
"» with byte string «$b»\n";
}
エンコードとデコード
IOシステムの仕様は非常に基本的なもので、エンコードとデコード用のレイヤはまだ定義されていません。この記事にSYNOPSISがないのはそのためです。 そのような機構が用意されるのは間違いなく、コードは次のようなものになると思われます:
my $handle = open($filename, :r, :encoding<UTF-8>);
正規表現とUnicode
正規表現はUnicode水準を指定する修飾子を取ることができ、m:codes/./
は丁度1個のコードポイントにマッチします。修飾子を指定しない場合は現在のUnicde水準が使われます。
(文字にマッチする)\w
のような文字クラスはUnicode標準にしたがって動作します。
修飾子として大文字小文字の無視(:i
)やアクセントの無視(:a
)、置換演算子の置換結果に大文字小文字やアクセントを反映するもの(:samecase
と:sameaccent
、省略形は:ii
と:aa
)があります。
MOTIVATION
今日のほとんどのツールやプログラミング言語で文字列を正しく処理するのはとても難しいことです。
Perl5で書かれたWebアプリケーションを作っているとして、長い単語がレイアウトを崩してしまわないように分割したいとしましょう。
組み込みのsubstr
を使ったりすると、意図せずして書記素が泣き別れになるかも知れません。
Perl6は書記素レベルの文字列操作を組み込みでサポートした最初の主要言語になります。 この文字列操作機能はUnicodeを使う上でほとんどの悩みを取払い、(正規表現と連携して)Perl6を文字列処理における最も強力な言語の1つにします。
テキスト用とバイト列用の個別のデータ型はデバッグとイントロスペクションを非常に容易にします。
コメント
コメントを投稿