2000年7月2日 p5p 本周
- 备注
- 更多 Unicode
- 加快方法查找速度
my __PACKAGE__ $foo
cfgperl
- 缺少的方法
- Windows 上的信号
- 新的
File::Spec
- 另一个令人沮丧的正则表达式引擎错误
s///
似乎更慢perlforce.pod
\&
原型现在工作- 呼吁短文档补丁
- 更多赏金
sprintf
测试- 回归测试和
@INC
设置 asdgdasfasdgasdf;jklaskldhgauklhc dhacb;dh
- 各种
备注
您可以通过发送空消息到 [email protected]
. 订阅此摘要的电子邮件版本。
请将更正和补充发送到 [email protected]
,其中 YYYYMM
是当前年份和月份。
更多 Unicode
Simon 继续生成 Unicode 补丁。
Unicode 处理 HOWTO
Simon 写了一个清晰而有趣的对 Unicode 是什么以及如何处理它的总结。如果您对所有的 Unicode 东西感到困惑,您确实应该 阅读关于它的内容。
Unicode 正则表达式匹配
Simon 还询问了如果你这样做会发生什么
$b = v300
v196.172.200 =~ /^$b/;
(这是一个问题,因为 $b
的 UTF8 表示实际上是值分别为 196 和 172 的两个字节。) 但 Gisle 说当然不应该匹配,因为目标字符串实际上并不包含字符 #300。
这导致了对正则表达式引擎应该如何处理 UTF8 字符串的简短讨论。这个问题追溯到 UTF8 实现的根源。
Larry 的最初想法是,如果 use utf8
在作用域内,操作将假定所有数据都是 UTF8 字符串,如果不是,则假定是字节字符串。这给程序员,尤其是模块编写者带来了很多负担。例如,假设您想要编写一个函数,该函数在其参数长度超过 6 个字符时返回 true
sub is_long {
my ($s) = @_;
length($s) > 6;
}
不,这不会工作,因为如果调用者传递了一个 UTF8 字符串,那么你的答案将是否字符串长度超过六个 字节,而不是六个字符。(记住,UTF8 中的字符可能比一个字节长。)您必须编写如下内容
sub is_long {
my ($s) = @_;
if (is_utf8($s)) {
use utf8;
length($s) > 6;
} else {
length($s) > 6;
}
}
这种方法在几个版本前被放弃,原因很明显。当前的方法是每个标量都携带一个标志,表示它是否是 UTF8 字符串或纯字节字符串,操作如 length()
被重载以同时支持这两种类型的字符串;length()
不论字符串是否是 UTF8 都返回字符串中的字符数。
现在有一个肮脏的秘密:以这种方式重载正则表达式引擎是困难的,并且尚未完成。正则表达式匹配忽略了目标中的 UTF8 标志。相反,它使用被放弃的旧方法:如果它是在作用域内使用 use utf8
编译的,它假定其参数是 UTF8 格式,如果不是,则假定其参数是字节字符串。
在这里正确的事情是修复正则表达式引擎,使其行为取决于目标中的UTF8标志。最困难但也是正确的方法是真正修复正则表达式引擎。更简单的方法是让正则表达式引擎像use utf8
不在作用域内一样编译所有内容,然后稍后如果它被用于匹配UTF8字符串,应该像use utf8
被启用一样重新编译正则表达式,并将新编译的正则表达式与原始正则表达式一起存储起来,以便用于UTF8字符串。
I18N 常见问题解答
Jarkko发布了一个链接,指向James撰写的关于Perl I18N/L10N的非常棒的FAQ。
规范化
这导致Simon询问Perl是否应该支持规范化。什么是规范化?Unicode有一个字母“e”的字符(U+0065),还有一个字符表示重音符号(U+00B4),看起来像´,称为“组合字符”,因为它与后面的字符结合以产生带重音的字符;当包含重音符号的字符串显示时,重音符号应该叠加在之前的字符上。但Unicode也有一个字母e带重音符号的字符(U+00E9),如é。这应该以与U+00B4 U+0065这两个字符序列相同的方式显示。
Perl目前不这样做,如果你有两个字符串,一个由pack "U*", 0xB4, 0x65
生成,另一个由pack "U*", 0xE9
生成,它将它们报告为不同的,这当然是对的。但显然,对于某些应用,你希望它们被视为等效的,而Perl目前没有内置函数来识别这一点。
Sarathy表示,我们确实想要这个功能,但不是在基本功能工作之前。
Simon 停止对 Unicode 的工作
Simon宣布暂时停止他的Unicode活动;他接下来将致力于行处理功能。
他还表示,如果有人能帮助他处理Unicode和行处理,他会很高兴。
加快方法查找速度
Fergal Daly指出,Doug的补丁会破坏抽象基类,因为它将use Dog $spot
的语义扩展为新的含义。以前,这意味着$spot
保证用伪散列表实现,并且$spot
中的字段保证是%Dog::FIELDS
中指定字段的子集。Doug的补丁现在添加了这样的含义:对$spot
的方法调用将在编译时通过在类Dog
中查找它们来解决。这是一个变化,因为以前允许将$spot
赋值为Dog
的子类(例如Schnauzer
)的实例,只要它的字段布局与%Dog::FIELDS
兼容。但现在你不能再这样做,因为当你调用$spot->meth
时,你会得到Dog::meth
而不是Schnauzer::meth
。
哎呀。
随后进行了一些讨论。Sarathy建议,只有在编译结束时Dog
没有子类时才启用优化。Fergal说,将优化限制在这样情况下是件遗憾的事,并且为任何在子类中没有重写的任何方法启用优化并不会难多少。
讨论正在进行中。
my __PACKAGE__ $foo
Doug MacEachern提交了一个补丁,允许使用my __PACKAGE__ $foo
,其中__PACKAGE__
代表当前包名。关于代码膨胀的成本是否值得收益进行了一些讨论。Doug表示,这与__PACKAGE__
在任何其他地方有用的原因相同。(作为一条旁注,为什么“bloat”这个词除了与三行补丁相关之外,永远不会被使用?)
Andreas Koenig 表示,如果允许使用 my CONSTANT $foo
(其中 CONSTANT
是任何编译时常量,例如由 use constant
创建的常量),会更好。Doug 也提供了一份修改后的补丁来实现这一点。
Jan Dubois 指出,这将破坏现有代码,其中存在与现有补丁同名的编译时常量。Andreas 并不在乎。
Andreas Koenig: 任何使用与现有和实际使用的类同名常量的程序员都不是在干净地编码,应该直接被淘汰。
更有说服力的是,他指出,在这种情况下,my Foo $x = Foo->new
也不会工作,因为右边的 Foo
将被解释为常量,而不是类名。
然后 Doug 提交了一个更新的补丁,它也允许使用 my Foo:: $x
。
cfgperl
上周我给很多人发了电子邮件,询问 cfgperl
是什么,以及为什么在 Jarkko 的网站上出现了一个似乎更新的秘密源代码库。我担心有一个内圈在开发,有一个隐藏的开发分支,对其他人不可访问。
Jarkko 在电子邮件中详细回答了我,然后在 p5p 上发帖解释了实际情况。cfgperl
只是 Jarkko 的 私人 源代码副本的名称,他会在其中应用他认为值得的补丁。它领先于主仓库,因为 Sarathy 上个月在休息。
缺少的方法
Richard Soderberg 回应了我的补丁请求(参见 上周的讨论),并产生了一个。非常感谢,Richard!
Windows 上的信号
Sarathy 说,在 Windows 下无法正确模拟信号,但人们仍然一直在抱怨。所以他提交了一个补丁,试图注册信号处理程序,我想是为了阻止他们抱怨。
新的 File::Spec
Barrie Slaymaker 提交了一系列对 File::Spec
套件的更改。
另一个令人沮丧的正则表达式引擎错误
这可能导致当它们应该是 undef 时,回溯变量被错误地设置。显然,状态在回溯时并不总是正确恢复。
s///
似乎更慢
Perl Lindquist 报告了一个 s///
的例子,在 5.6.0 中的运行速度比在 5.004_03 中慢得多。正则表达式很糟糕,因此你会期望是二次搜索,但 Mike Guy 报告说实际上 Perl 在进行三次搜索。
perlforce.pod
Simon 声称这份文档已经三年了,他只是发送了一个小的更新,但我没有在我的开发源代码副本中找到它。
这是一份关于如何使用 Perforce 仓库的文档,其中存放着 Perl 源代码的主副本。
\&
原型现在工作
Larry 发送了一个补丁,允许函数在原型中使用 &
。它似乎与 &
同义。
呼吁短文档补丁
正则表达式中的 _
序列现在会引发警告,而之前则不会。Dominic Dunlop 跟踪到引入此补丁的补丁,并指出它需要文档(在 perldelta
和可能 perldiag
)以及可能还需要一个测试用例。但没有人站出来。这是一个很容易为文档做出贡献的机会。
更多赏金
Dominic Dunlop 报告了一个新的 printf "%v"
指定符中的有趣漏洞。这个漏洞可能不太难调查和修复,因为它可能只局限于 Perl 的小部分,这部分与 Perl 的特殊数据结构没有太多关系。因此,这对于初学者来说是一个很好的工作。如果你感兴趣并且需要帮助确定开始的地方,请给我留言。
sprintf
测试
多米尼克还发送了一个补丁,向 t/op/sprintf.t
添加了 188 个新的测试。
回归测试和 @INC
设置
之前,尼古拉斯·克拉克指出,如果你选择不构建 Perl 的所有标准扩展模块,如 Fcntl
,则许多回归测试将会失败。
尼古拉斯为解决这个问题开发的分支,讨论了确保测试获得库的测试版本而不是之前安装的版本的最佳方法。尼古拉斯使用的是
unshift '../lib';
这是测试文件中常见的一个惯用语。它有什么问题?它将标准目录保留在 @INC
中,这可能不合适,并且它假设库在兄弟目录中,所以你必须在自己所在的 t/
目录中运行测试。
这里有一点点关于正确做法的讨论。迈克·盖伊建议一个解决方案可能是测试框架首先正确设置环境。问题是那样的话你将无法在没有框架的情况下运行测试。(例如,你可能只想运行单个测试文件;目前你可以说 perl t/op/dog.t
或类似的命令。)
萨拉蒂指出,如果每个测试文件以类似
BEGIN { @INC = split('|',$ENV{PERL_TEST_LIB_PATH}
|| '../lib') }
的方式开始,可能会解决这个问题。然后框架可以设置 PERL_TEST_LIB_PATH
,但你仍然可以在正确的位置手动运行单个测试。
asdgdasfasdgasdf;jklaskldhgauklhc dhacb;dh
来自捷克共和国的另一份垃圾错误报告。第一次看到的时候很有趣;这次就不那么有趣了。
嘿,捷克小子!别再用 perlbug
测试你的键盘线,否则我会去你家,砍掉你所有的八根手指。
各种
大量错误报告、错误修复、非错误报告(你可以用数字作为参考!)问题、答案,以及少量垃圾邮件。不要发火。
下周见,您的谦卑、顺从的仆人,
标签
反馈
这篇文章有什么问题吗?请在 GitHub 上打开一个问题或拉取请求来帮助我们。