本周在 p5p 1999/11/21
本周在 perl5-porters
(1999年11月15-21日)
- 备注
XSLoader.pm
- 线程
- 共享解释器线程(当前模式)
- 克隆解释器线程(将在5.005_63中推出)
chomp()
- 线程和正则表达式
Safe::Hole
PREPARE
- 序列化模块
LWP
中的本地地址- 将
select()
和chdir()
local()
化 - 漫游环境
- 本地赋值
goto
超出local
范围use foo if bar
;croak
使eval
复杂化- 控制反斜杠
while()
中的空条件- 未定义函数警告
- 静态扩展
- POD 演技
- Perl 艺术
localtime()
竞赛继续- 各种
备注
我以为这将是一个平静的一周,但然后砰的一声,周五收到了140条消息。幸运的是,其中大部分可以忽略。我提到过这些报告是通过 O’Reilly 和合作伙伴的慷慨提供的,他们支付我薪水吗?
下周的报告将会晚些,因为周日我将与 Perl Mongers 一起在伦敦。预计下个月初会收到下一份报告。
您可以通过向 [email protected]
发送空消息来订阅此摘要的电子邮件版本。
请将更正和补充发送到 [email protected]
,其中 YYYYMM
是当前年份和月份。
XSLoader.pm
Ilya 贡献了一个新的模块,XSLoader
,这是 Dynaloader
的精简版。它使用更少的内存,并且具有更简单的接口。他修补了标准动态加载的模块以使用 XSLoader
而不是 DynaLoader
。 了解更多信息。
线程
Dan Sugalski 提交了一个补丁,使一个新的锁定宏可用于 XS 代码,但 Sarathy 说
每次我看到人们在修补
USE_THREADS
代码时,我都会想这会不会是徒劳的。我不认为在需要大量加锁的情况下,挽救现有的USE_THREADS
模式有很大的希望。
以防你错过了这个要点:5.005_63 将会有一个与之前版本 Perl 完全不同的线程模型。我要求 Dan 向我解释这两个模型,他非常友好地提供了以下内容
这个线程模型非常接近大多数人想到线程时想到的内容。有一个单一的、共享的可执行文件(或 optree,在 Perl 的情况下),以及一个单一的变量池。任何线程都可以看到并影响其词法作用域内的任何内容。线程之间的数据共享成本低廉,但程序员有责任保持一致性。
作为一个类比,考虑一个线程是一只仓鼠,而你的程序是一个巨大的迷宫。启动另一个线程意味着将另一只仓鼠释放到环境中。线程之间不会真正碰撞(你见过两只仓鼠卡在迷宫管道中吗?),但保持两只或更多仓鼠同时在一个锻炼轮上运行的唯一方法是精心设计集合。
克隆解释器线程(将在5.005_63中推出)
这个线程模型更接近传统的 Unix fork 模型。每个线程都有一个 optree 的副本。除非明确共享,否则一个线程不能看到或影响另一个线程中的任何内容。线程之间的数据共享和协调成本适中,但有些繁琐,Perl 解释器的责任是防止一个线程干扰另一个线程的玩具。
继续使用仓鼠的类比,在这个模型中创建一个新的线程相当于为你的新仓鼠提供了一个全新的、独立的跑轮通道。这两个跑轮通道可以共享运动轮,但只限于非常具体、明确的位置,并且内置了小的隔离门,以确保一次只有一个仓鼠能在轮子上。
我个人的喜好有些矛盾——我想要共享线程,因为它们让我可以构建各种便宜、巧妙的工具(线程对象和可子类的 Thread::Object
,这些都很简单。我知道,我为此编写了一个包。每个对象一个线程。哇!),但我觉得大多数人(包括我在编写“常规”代码时)更倾向于使用克隆线程提供的安全保护。
更具挑战性的部分是在幕后。让 Perl 具有线程安全性(也就是说,即使程序员没有同步访问,它也不会崩溃或段错误)是一个头疼的问题。我已经尝试了几个不同的计划——第一个是过度谨慎的,第二个让 libperl.so
壮大了很多,包含了大量的阴影例程用于 XS,第三个如果线程已经死亡,我就不再费心去考虑了。
它也会消耗更多的内存。要做到正确,每个变量都需要一个互斥锁,否则你会遇到死锁问题和不必要的锁定竞争。当然,这也使得 $foo[time]
的成本比现在还要高。另一种选择是“不要那样做”,但这并不是我喜欢的选择。
大多数有观点的 p5p 人都更喜欢分叉版本。我想他们都是错的,但这只是我的看法。:-)
非常感谢,Dan。
Dan 要求 Sarathy 在现有的线程模型上做出决定。Sarathy 表示他还没有确定,因为他需要看到新方法的效果,但他猜测 Perl 会采用新方法。
chomp()
Ben Tilly 提问是否可以将 chomp()
制作成可以删除 "\n"
、"\r"
或 "\r\n"
中的任何一个。当然,这是不可能的。
Mike Guy 指出,其他人也同意,正确的解决方案是让 I/O 子系统确定它正在读取的文件类型,并将行结束转换为 \n
,无论它们最初可能是什么。这属于“行管理”的一般标题。
Larry Wall:说真的,我们正进入一个时代,输入的模糊行为将成为必要的恶。我希望情况不是这样,但我的神旨已经不多。
线程和正则表达式
几周前,Rob Cunningham 报告说他和 MIT 的 Brian Mancuso 正在修复线程化 Perl 中的正则表达式。周五,Brian 发来邮件,提交了他的补丁。Ilya 不喜欢它,因为它通过全局变量而不是通过垫子间接访问匹配变量(这是正确的做法),并且他认为 MIT 的解决方案会缓慢。Rob 回复说,他们需要它现在就能工作,并且它能够工作比它快速更重要。请参阅Sarathy 对补丁的回复
可能是最发人深省的。Rob 说,他们可能没有时间正确地做这件事。
Safe::Hole
Yasushi Nakajima 宣布了一个新的模块,Safe::Hole
,它允许你将子例程安装到 Safe
间隔中,以便它可以由间隔中的代码调用,但仍然在原始间隔中运行;类似地,你可以将对象安装到间隔中,以便对对象的调用会超出间隔。Yasushi 的示例是
假设您有一个CGI程序,希望在安全隔离器中评估一些用户代码,并给它访问CGI
对象的能力。仅仅将CGI
对象安装到隔离器中是不够的,因为这样对象的方法将不可访问。相反,将CGI
对象包装在Safe::Hole
对象中,并将Safe::Hole
对象安装到隔离器中。现在您可以在隔离器内对Safe::Hole
对象进行方法调用,它们将被转发到外部适当的子例程。
PREPARE
( 早期的摘要)
根据Sarathy的早期请求,Ilya重新整理了他早期的PREPARE
补丁,以便通过编译时pragma启用PREPARE
方法的调用。
序列化模块
David Muir Sharnoff有一些模块,类似于MLDBM
,需要与一个未知的序列化模块(如Storable
或Freezethaw
)通信。上周,他注意到MLDBM
中包含大量代码,这些代码告诉它如何与这些各种序列化器通信。David建议,序列化模块的作者尝试遵守一个共同接口。
MLDBM
的作者之一Raphael Manfredi表示,这不太可能,因为不同的序列化模块有不同接口,这有其合理的原因,即它们并不都做相同的事情。例如,Storable
有一个nstore
方法,它保证了网络字节序。但是,字节序与Data::Dumper
使用的表示无关。
然后David建议有人从MLDBM
中提取序列化器接口代码,以便它可以为需要序列化器的其他模块所借用。如果有人在寻找一个有用的项目来做,这可能是一个好机会。
LWP
中的本地地址
几周前 Gisle Aas建议让IO::Socket
注意LocalAddr
环境变量。本周,Graham解释了这为什么会是一个坏主意。
将 select()
和 chdir()
local()
化
Jeff Pinyan建议扩展local()
以适用于这些,尽管他没有提供补丁。我指出,这样的语义已经通过像SelectSaver
这样的模块实现,而且Alias
模块展示了如何将XS模块导出为任意语义,这些语义在退出块时将自动撤销。我还指出(显然不太清楚,因为Sarathy在下一条消息中重复了它),可以很容易地编写一个XS模块,该模块指定在块退出时调用任意用户提供的匿名函数;然后可以很容易地编写一个temp_chdir()
函数,其效果在块结束时自动撤销。应该有人编写这个。
漫游环境
Joerg Schumacher发现了一个核心-dmuping错误。以下是解释:他使用Term::Readline::Gnu
模块。当加载此模块时,它会检查LINES
和COLUMNS
环境变量,并在它们不存在时安装它们。它使用putenv
函数进行此操作,在这种情况下putenv
重新定位整个环境。之后,他使用%ENV
散列设置一个环境变量。通常,第一次设置环境变量时,perl会将环境重新定位到其他地方,以便以更方便的方式进行内存管理,包括释放单个环境变量字符串。Perl如何知道这是第一次呢?它将环境的当前位置(environ
)与perl启动时的环境位置(PL_origenviron
)进行比较;如果它们相同,它将重新定位环境。
然而,在Joerg的情况下,环境已经被putenv()
重新定位。本应成功的“首次”测试失败了,Perl认为它已经自己重新定位了环境。然后它试图在它认为已经分配但实际上没有分配的环境上执行内存管理,结果是核心转储。Joerg提供了一种补丁,让Perl保持一个显式的布尔变量,记录是否已经移动了环境,而不是依赖于检查是否与Perl开始时相同的位置的欺骗性测试。
Ilya似乎没有理解问题描述,与Joerg争论了很多,但如果他的论点中有什么是我无法理解的,我也无法分辨。Joerg在整个过程中都非常耐心。
然后Tom和Ilya进行了一场无用的争论,这应该是在私人电子邮件中进行的。
这个主题中有五十四条消息。我将慷慨地授予它1.21e-01的S/N比率。
本地赋值
Andre Pimlott报告说
{ local ($/ = undef); ... }
不仅没有做想要的事情,而且似乎什么都没做。例如,有人建议它首先将赋值给$/
,然后进行本地化,但这似乎不是这样。)这似乎是一个真正的错误。
goto
超出 local
范围
Ilya抱怨使用神秘的goto
退出local
的作用域会撤销本地化
$a = 5;
sub a { print $a }
sub b {local $a = 9; goto &a}
b();
这会打印5,而他希望打印9。(注意,Ilya的原始报告包含一个错误;他有local $b
而不是local $a
。)他想要这样做的目的是为了能够这样做
local @ISA = (@ISA, 'DynaLoader');
goto \&DynaLoader::bootstrap;
Nick Ing-Simmons建议他这样做
{
local @ISA = (@ISA, 'DynaLoader');
&DynaLoader::bootstrap;
}
当然,这会在调用栈上留下原始调用,因此(例如)来自Carp
的消息可能会弄不清楚从哪里报告错误。在Carp
的情况下实际上没有问题。讨论突然中断。
use foo if bar
;
Ilya贡献了一个补丁来启用这种语法,以及类似的unless
。它是通过伪造一个BEGIN
块来做到这一点的,但没有真实块的作用域效应。(作用域效应是程序员最初不能在这里简单地使用BEGIN
的原因。)
Steve Fink对Ilya的补丁进行了修订。Tom Christiansen发送了一条巨大的消息,抱怨这个特性是另一个奇怪的特殊情况。随后进行了一些关于替代方案的讨论,但没有得出我能够看到的结论。
Tom Christiansen建议一个no scope
指令,这将“消除”一组花括号。然后你可以这样说
BEGIN {
no scope;
if (SOMETHING) {
no scope;
use integer;
}
}
no scope
声明将提升use integer
指令的效果,使其作用持续到文件末尾。
Larry对此说了很多有趣的事情;最直接的是,类似use comppad
的东西应该只是将声明推到正在编译的任何代码的最顶部。
Ilya说这种行为已经可以通过使用提示变量$^H
或%^H
的任何模块获得。
croak
使 eval
复杂化
David Blumenthal报告了IPC::Open3
中的一个问题:它会产生一个子进程,尝试执行你的命令,如果不行,子进程会崩溃。如果open3
调用在eval
块内部,这意味着子进程从eval
块返回而没有退出,你的程序会得到一个巨大的惊喜。David建议它应该使用carp
而不是崩溃,然后调用exit
。
我提到这一点是因为可能有很多其他模块存在类似的问题。模块永远不应该调用croak
或die
。
控制反斜杠
Philip Newton 指出,无法使用 \c
符号生成控制反斜杠。无论是 "\c\"
还是 "\c\\"
都不起作用。前者会抱怨不匹配的引号,而后者会生成一个控制反斜杠后跟一个普通反斜杠。(例如,\x1c
和类似的是可以工作的。)
关于这一点,在 perlop
中有详细的解释,标题为《解析引用构造的可怕细节》。
while()
中的空条件
Greg Bacon 报告称:
while () { CODE }
是合法的,并且是一个无限循环。这实际上不是一个错误;因为当你从 for (;;)
块中省略条件时,你应该得到一个空循环,而且 for(;;)
和 while()
是一样的。Larry 甚至表示,他故意在 Perl 1 中允许在 while()
中使用空条件。Ilya 询问为什么不把它去掉,类似于 if BLOCK BLOCK
的方式被去除。Larry 指出,这两种情况实际上并不相似:if BLOCK BLOCK
是完全意外地被移除(或破坏)的,而且这个错误从未被修复的唯一原因是没有人对此提出过任何意见。
未定义函数警告
Mike Taylor 写信要求一个警告,该警告会在编译时宣布存在对未定义函数的调用。Dan Sugalski 列举了一些原因,说明为什么还没有这样的警告:AUTOLOAD
函数;受 if ($^O eq 'Eniac')
保护的平台特定函数调用;通过 require
加载的函数;人们在对符号表做奇怪的事情。
Tom Christiansen 指出,perl -MO=Lint,-context,-undefined-subs program
已经做了类似的事情。这似乎让 Mike 满意。
静态扩展
Margie Levine 询问关于编译与静态链接扩展的 Perl。Andy Dougherty 回复说,所有的文档可能都已经丢失,最好的办法是在运行 Configure
之前将它们直接放入 ext/
目录中,Configure
应该会注意到这些扩展并将它们作为标准集的一部分来构建。
POD 演技
Ilya 指出,像这样的结构
C<S<
code with I<..> or L<...> escapes or whatever
>>
将生成一个缩进的代码段落,该段落仍然可以包含 pod 转义,用于超链接或其他内容。
Perl 艺术
Greg Bacon 报告了一个娱乐内容。(背景是 Perl 代码。)关于在类似媒介中生成羊驼和其他图像的讨论。
localtime()
竞赛继续
试着猜猜明年将提交多少关于 localtime()
函数的错误报告。访问 http://www.plover.com/~mjd/perl/y2k/y2k.cgi。
各种
大量关于错误报告、错误修复、非错误报告、问题、答案以及少量无意义的言论。(这周没有垃圾邮件。)
直到下周,我是您谦卑而顺从的仆人:
标签
反馈
这篇文章有什么问题吗?通过在 GitHub 上打开一个问题或拉取请求来帮助我们。