本当は[言語]タグではないような。
MozillaハッカーであるRobert O'Callahanによる、 「UTF-16はダメ、UTF-8でいいじゃん」という話。
私も前に書いたような気がするけど、 UTF-16は良くない。まず、第一にUTF-16はバイト単位のCES(Character Encoding Scheme)でないので エンディアンの影響を受ける。これは結局同じ名前で2種類のCESがあるのと同じである。
それを区別するための方策がBOM(Byte Order Mark)だが、 これが輪をかけてよくない。 BOMの文字としての意味は「ZERO WIDTH NON-BREAKING SPACE」なので、 これは見えない文字である。付いているかどうかひと目でわからない文字は 面倒なだけである。うっかり文字列やファイルの途中に混じってしまったら目も当てられない。
さらにその全身前身であるUCS2と比較して、
UTF-16は固定長ではない。ので、n番目の文字をアクセスするコストは
普通に実装すればO(n)である。
UCS2の頃に重大な選択を「してしまった」Javaとかはともかく、 これから選ぶならUTF-16はありえない。 もう、ダメの三連荘。
UTF-16がダメなら、なにを選ぶのか。 ここではUTF-8を推奨している。私も(条件つきで)賛成する。
UTF-8は、エンディンアン問題と無縁である。 BOMも不要だ(付けられるけど)。メモリ効率もUTF-16よりはずっといいし。 可変長であるという点はUTF-16同様だけど、 それもそんなに問題ではない。
というのも、そもそもn番目の要素へのアクセス(ここではCharAt(n)と呼ぶ)は そんなに登場しないからだ。実際に頻繁に現れるのは 文字の検索であり、それはもともとO(n・m)だったりするし、 UTF-8でBoyer Mooreを実装するのもたやすい(今のRubyはKarp Rabinを使ってるけど)。
LarcenyというScheme処理系でどのように文字列を表現するか、という話。 前にShiroさんが話してたものだね。
紹介されているのは以下の7通り。
興味深いのはやはりrecord2やrecord1。 ただ、これってSchemeに閉じている時にはいいんだけど、 Cから文字列がほしい時にはrecord1やrecord2のフォーマットのままでは困るので、 毎回UTF-8なりUTF-16なりに変換してやる必要が出てきそうだ。 そうなったときに、変換やメモリ割り当てのコストがどのくらい効いてくるかが 興味深いところだ。少なくともRubyでは難しそうだなあ。