Ada 202x (28日目) - Is_Basic/To_Basic¶
文字コード話はネガティブにならざるを得ないのでさっさと終わらせましょうね。
経緯¶
Ada.Characters.Handling にある Character を扱う関数のうち(ISO_646 こと7ビットASCII関係を除けば) Is_Basic と To_Basic の2つのみ Wide_Character/Wide_Wide_Character 版が存在していませんでした。
Ada 202xでの改善¶
Wide_Character 版にあたる Ada.Wide_Characters.Is_Basic と To_Basic が追加されました。
Ada.Wide_Wide_Characters.Handling は Ada.Wide_Characters.Handling 同様と定義されていますので自動的に Wide_Wide_Character 版も追加されることになります。
Ada.Wide_Characters.Is_Basic¶
Ada.Wide_Characters.Is_Basic は引数の文字が正規分解(canonical decomposition)できるなら False 、それ以上分解できなければ True を返します。
Ada.Wide_Characters.To_Basic¶
Ada.Wide_Characters.To_Basic は引数の文字が正規分解できるなら分解後の基底文字(base character)を返します。
分解できなければ引数をそのまま返します。
ライブラリの実装が使用しているUnicodeのバージョンは Ada.Wide_Characters.Character_Set_Version で調べることができます。
関連AI¶
AI12-0260-1 Functions Is_Basic and To_Basic in Wide_Characters.Handling
所感¶
めでたしめでたし、で済ませたいのです。 はい、例によって書いておきたいことが。 ただの個人の日記ですので例によって読むだけ損です。
Ada.Characters.Is_Basic¶
Ada.Characters っていつから存在していると思います?
Unicodeの最初のバージョンISO/IEC 10646-1:1993が1993年です。
Ada.Characters が追加されたAda 95は勿論1995年。
時期としては近いので微妙なところです。 勿論どちらの規格も制定の何年も前から練られていたわけです。
結論から書いてしまいますとAda 95ではISO 10646のBMPに対応する16ビット文字型の Wide_Character/Wide_String 、ライブラリとしては Ada.Strings 以下の Wide_* 版や Ada.Wide_Text_IO 等が追加されましたが、これらは言わばコンテナで中身については何もありませんでした。
Wide_Character の中身を具体的に扱う Ada.Wide_Characters の登場はAda 2005からです。
そのような時期的な理由で Ada.Characters.Is_Basic はUnicodeを意識した定義にはなっていません。
True if Item is a basic letter. A basic letter is a character that is in one of the ranges 'A'..'Z' and 'a'..'z', or that is one of the following: 'Æ', 'æ', 'Ð', 'ð', 'Þ', 'þ', or 'ß'.
というわけで動作を比較しますとこうなるわけです。
引数 |
|
|
|---|---|---|
上記の基底文字 |
True |
True |
その他基底文字 |
False |
True |
合成済み文字 |
False |
False |
結合文字 |
(Latin-1の範囲にはなし) |
True |
それ以外 |
False |
True |
Ada.Characters.Is_Basic は丁度 Ada.Wide_Characters.Is_Basic と Is_Letter との論理積を取ったような動作です。
Latin-1の範囲ではアルファベットにしかダイアクリティカルマークは付きませんからこの動作でも良かったですがUnicodeではどんな文字でも合成することができます。
そのため Ada.Characters.Is_Basic と互換をとっても使い物になりません。
しかし別物に同じ名前が付いていますと Character と Wide_Character 両方に対応する generic なコードを書くのに支障が出ます。
generic
type Character_Type is (<>);
with function Is_Basic (Item : Character_Type) return Boolean is <>;
package Generic_Something is
みたいなやつです。
当時、別物には別の名前を付けてくれと訴えましたが、AIの提案者のJ-P. Rosen先生本人に
If you are adapting a program to use the full BMP instead of Latin1, expect many more difficult issues and/or incompatibilities than this one...
と言われてしまいました……。
Latin-1用のコードをUnicode用に書き換えるならこんな小さな非互換より大変なことは一杯ある、ということですね……。
幸い To_Basic の方には差はありません。
generic なコードを書くときは To_Basic のみを用いて分解できるかの判定は To_Basic (Item) /= Item とすればいいでしょう。