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
とすればいいでしょう。