Perl 6 转换组合字素?

Perl 6 transforms combined graphemes?

两个代码点怎么可能变成一个?如果这是处理组合字素的默认方式,如何避免它?

> my $a = "a" ~ 0x304.chr
ā
> $a.codes
1
> $a.ords
(257)

UPD:阅读 documentation 后,我发现所有输入都已标准化:

Perl6 applies normalization by default to all input and output except for file names which are stored as UTF8-C8.

那么,有没有一种方法可以避免规范化,即在不改变编码的情况下获取输入并对其进行处理?

根据 Unicode 报告(参见 here),一些字符有多种表示方式。根据该报告:

Certain characters are known as singletons. They never remain in the text after normalization. Examples include the angstrom and ohm symbols, which map to their normal letter counterparts a-with-ring and omega, respectively.

...

Many characters are known as canonical composites, or precomposed characters. In the D forms, they are decomposed; in the C forms, they are usually precomposed.

在您提供的示例中,$a 包含可以用两种方式表示的字符串。首先,它对应于 U+0101(带有 MACRON 的拉丁文小写字母 A),这是一个 Unicode 代码点。其次,它可以表示为两个代码点,它们组合起来形成一个等效字符(U+0061 [拉丁小写字母 A] 后跟 U+0304 [COMBINING MACRON])。

这两种表示法是NFC和NFD的基础。这些被称为 规范化 形式,因为它们允许使用最简洁或最解构的可用表示形式定期表示字符。某些组合字符在 Unicode table 中可能有两个条目(例如 Ohm 和 Big Omega),但规范化形式仅映射到一个条目。

NFD 将所有字符分解为用于构成这些字符的所有代码点的列表,确保不使用预组合字符。

Perl6 自动使用 NFC 表示,但您可以通过在 Str 上使用 NFD 转换方法获得 NFD(或 Decomposed)版本.

my $a = "a" ~ 0x304.chr;

say $a.codes;                 # OUTPUT: 1
                              # This is because the concatenation
                              # is using NFC by default.
say $a.ords;                  # OUTPUT: (257)

say $a.NFD.codes;             # OUTPUT: 2
say $a.NFD.list;              # OUTPUT: (97 772)

NFC 和 NFD 都很有用,但目的不同。据我所知,没有办法避免输入规范化,但您可以使用 NFCNFD 转换方法将输入转换为您需要的任何表示形式。