这确实是一个双重问题,我的两个最终目标有以下答案:
- 就机制而言,标准的字符串比较顺序是什么?
- 什么是更好的名称,以便我可以更新文档?
Perl 的排序文档说,没有块,sort
使用“标准字符串比较顺序”。但是这个命令是什么?它应该有一个更好的名字。对于这个问题,我特别指的是语言环境无效的情况,因为它定义了它自己的顺序。
在过去的几年里,我们通常将标准排序顺序称为“ASCIIbetically”。它在学习 Perl和许多其他书籍中。但是,该术语已过时。Perl 从 5.6 开始就支持 Unicode。谈论 ASCII 是老派。因为 Perl 也支持 Unicode,所以它知道字符串。在sv.c中,Perl_sv_cmp
了解locale
、bytes
和 UTF-8。前两个很容易。但我对第三个没有信心。
/*
=for apidoc sv_cmp
Compares the strings in two SVs. Returns -1, 0, or 1 indicating whether the
string in C<sv1> is less than, equal to, or greater than the string in
C<sv2>. Is UTF-8 and 'use bytes' aware, handles get magic, and will
coerce its args to strings if necessary. See also C<sv_cmp_locale>.
=cut
*/
当 Perl 使用 UTF-8 进行排序时,它真正的排序是什么?字符串编码的字节,它代表的字符(可能包括标记?),还是其他?我认为这是 sv.c 中的相关行(提交 7844ec1 的第 6698 行):
pv1 = tpv = (char*)bytes_to_utf8((const U8*)pv1, &cur1);
如果我没看错(使用我生锈的 C),pv1
则被强制转换为八位字节,转换为 UTF-8,然后转换为字符(在 C 意义上)。我认为这意味着它是按 UTF-8 编码排序的(即 UTF-8 用来表示代码点的实际字节)。另一种说法是它不对字素进行排序。我想我几乎已经说服自己我没看错,但你们中的一些人比我更了解这一点。
由此,下一个有趣的行是 6708:
const I32 retval = memcmp((const void*)pv1, (const void*)pv2, cur1 < cur2 ? cur1 : cur2);
对我来说,这看起来就像曾经有pv1
和pv2
,被强制到char *
,现在只是逐字节比较,因为它们被强制到void *
。会发生这种情况吗memcmp
,看起来它只是根据我迄今为止阅读的各种文档比较位?同样,我想知道我在从 bytes->utf8->char->bytes 的旅程中缺少什么,比如可能是 Unicode 规范化步骤。Perl_bytes_to_utf8
在utf8.c中签出并没有帮助我回答这个问题。
作为旁注,我想知道这是否与Unicode Collation Algorithm相同?如果是,为什么Unicode::Collate存在?从表面上看,我不认为 Perlsort
处理规范等价。