返回信息流发信人: happierbee (吾生也有涯,而知也无涯), 信区: Perl
标 题: Ten Perl Myths
发信站: 水木社区 (Tue Jul 8 22:44:57 2008), 转信
看到一篇好文章,随便翻译了一下,没有完全按原文,大意应该不会错。有兴趣的
可以直接看原文。
作者: Simon Cozens
原文:http://www.perl.com/pub/a/2000/01/10PerlMyths.html
* 简介
当你想起或听到 Perl 时,可能会发现有许多关于 Perl 的错误信息。这会让很多
不熟悉 Perl 的人已经很难接受这门语言。这里我将选择前十个关于 Perl 的谣言
一一回答。我不是要说服你使用 Perl,只是希望你知道你听到的不一定是正确的。
至于 Perl 是不是对你合适,只有试一试才知道。
首先需要明白的是 Perl 是干什么的。 Perl 是一种通用的编程语言。如果问“我能
用 Perl 干这个吗?”,通常答案都是“可以”。你可以用它完成琐碎的系统管理工作
,CGI 或其它网络开发,但这绝不是全部。你将看到 Perl 完全可以胜任大型的项
目。
Perl 有时候也被称为是脚本语言,但是通常这样说的人是不喜欢 Perl 或不理解
Perl 的人。首先,程序和脚本之间没有本质的差别,它们都是告诉计算机你想要做
什么。其次,即使有差别,Perl 至少也是像 Java 或 C 那样的脚本语言。我将要
说的是 Perl 程序,你也可能听到其它人称之为 Perl 脚本。但是称它们为程序的
将会写出更好的程序。
* Perl 很难
人们会告诉你的第一件事是 Perl 很难:难学,难用,难理解。因为 Perl 很强大
,所以它就应该很难,不是吗?
错。Perl 从开始就是在几种语言基础上产生的,它对于每个程序员都将是很熟悉的
。你会 C 吗?如果会,你已经为学习 Perl 开了一个头。你会 Unix Shell 或者
awk、sed 编程吗?如果是的话,你将对 Perl 的语法感到像回家一样亲切。
即使你一点不会这些语言,即使你完全是刚刚开始编程,我还是要说 Perl 将是开
始学习编程的最简单的语言之一。我的理由有两个。
Perl 总是按你想的那样工作。Perl 的格言之一是:总有不只一种方法来做这件事
(There's more than one way to do it,TMTOWTDI)。人们总是用不同的方式来完
成工作,有时候甚至是完全不同的解决方法。Perl 就是这样,它不会强迫你使用某
种特殊的方式 (除非你被要求这样),它让你可以按自己的想法来表达你的编程意愿
。这有一个例子:假设我们有一个由冒号分隔的两列数据构成的文件。我们想要交
换这两列数据。某天,我们争论要怎样做这件事,这是我想到的方法:读入一行,
交换冒号两侧的内容,然后打印这一行。
while ( <> ) {
s/(.*):(.*)/$2:$1/;
print;
}
这个问题不是很难理解,所以解决起来也不是太难。它只要几行代码,实际上,如
果使用 perl 的命令行,你只需要上面的第二行。但是现在还是不要太关心这些技
术问题。
对于不太懂 Perl 的人,我稍作解释,第一行中的钻石符号表示读入一行,第二行
的 s 表示"替换"(substitute),括号表示记住 .* 匹配的任意内容。所以我们在读
入一行时,我们作了某种替换,然后打印出来。这个替换是什么呢?我们记录了冒
号前一部分内容和冒号后的一部分内容,替换成后一部内容,冒号和前一部分内容
连接的字符串。就是这样,很自然的想法。
但是,有些人选择用另一种方式:
while ( <> ) {
chomp;
($first, $second) = split /:/;
print $second, ":", $first, "\n";
}
有一点长,但是更容易明白 (或者更难明白)。关键是你怎样想的,Perl 不会强制
我们编程的想法。
我们简要的讲解一下:chomp 将换行符去除,然后将输入行由冒号分解成两个变量
,最后我们按相反的顺序打印出来。
第二个理由是你不需要理解语言的全部后才能完成你的工作。是的,对于前面这个
程序,我们可以在命令行中这样写:
% perl -p -e 's/(.*):(.*)/$2:$1'
(-p 表示 Perl 会循环的读入输入数据,在你处理完后再输出。)
但是我们不需要知道这些。你可以用一点点 Perl 的知识就能做很多事情。当然,
在你知道更多之后,做起来会更容易一些。
我们再看另一个例子,我们要查年 /etc/passwd 文件,显示出用户的一些信息。
Perl 是内建的函数用于读取这个密码文件,所以我们可以使用它们。但是,即使我
们不知道,我们也可以做,我们知道如何读入数据,怎样分割冒号分隔的文件,这
就是全部需要的。TMTOWTDI。
所以,Perl 和其它语言相似,它不会强制你按某种方式来想问题,你只学过一点
Perl 就能干很多事情,这样,我们可以很高兴的说 Perl 难学是假话。
* Perl 看上去就像是噪音
另一个可能听说的是 Perl 太丑,不干净,是只写语言。不幸的是,确实有许多程
序证实了这一点。但是不能因为你可以写很丑的程序,就说它是一种很丑的语言。
在混乱 Perl 代码比赛出现的很久以前就有混乱 C 代码比赛。
每次我看到 Perl 代码就像是 EBCDIC 噪音时,我不禁停下来想,什么导致这些人
写出这样丑的代码?过了很长时间,我才发现是 Perl 太容易使用才使得它容易混
乱。
我认为事情是这样发展的:当你需要将一个文件转换成另一种格式,5 分钟内,你
写出一个能工作的代码。它可能不很漂亮,但是它能完成工作。你保存下来只是防
止出现同样的问题。不久,你想根据情况的变化做一些修改,最后你得到一个很严
格的程序。你不想写一个很大的转换工具,但是很容易对现有程序作修改。代码重
用和快速开发联手缔造一个怪物。
问题是人们于是发布这个程序,因为它能工作,并且有用。于是其它人看了这个程
序后就说:“兄弟,你怎么能写这么丑的代码?”于是 Perl 就这样被搞坏了名声。
但是你是可以避免这样的事情发生。当你清楚会发生什么事时,你就要花一些时间
将你的程序重写一下,甚至可能是从头写一遍来保证可读性和容易维护。为了可读
性,你可以牺牲开发速度。
所以,用 perl 写一个干净的程序是完全有可能的。但是 Perl 不会替你做,取决
于你。
一句话,perl 不会写难懂的 perl,只有人会。如果你不去写这样的代码,你将同
意 perl 代码是噪音只是一个谣言。
* 正则表达式使 Perl 难学
正则表达式也是 perl 代码难读的一个原因。对于整个 Perl,正则表达式是非常强
大的。最基本的常识是你可以用它查找字符串中的内容,比如 /abc/ 用于查找 abc。
你还可以进行模糊查找,比如某种类型的字符:数字使用 \d 来匹配,对于匹配一
个数字和冒号,可以用 /\d:/。我们知道 . 匹配任意字符,还有 ^ 和 $ 用于指定
行首和行尾。目前都很容易对吧?匹配以两个数字开头的行,紧接着是一个任意字
符和逗号,可以用 /^\d\d.,/。
当你要匹配的东西变得复杂,正则表达式也会越来越复杂。你要记住的是正则表达
式和其它语言一样:要用它表达自己的想法,首先要学会和日常语言进行转换,直
到你会了这门语言为止。所以,即使我不能直接看明白 /^.,\d.$/是什么意思,但
是我可以读懂它。在行首,我们依次需要:一个任意字符,一个逗号,一个数字,
一个任意字符,最后是行尾。
当我们不只作匹配,还做替换时,我们还会产生更难看的东西。这是我最喜欢用的
一个例子,它用于修正 'teh' 和 'Teh' 为 'the', 'The':
s/\b([tT])eh\b/$1he/g
你可以坐下来,自己读读看。Perl 来允许你使用空白和注释打断正则表达式,所以
没有原因写一个不能明白的正则表达式。当你阅读编写了足够多的正则表达式之后
,你会在头脑中作这样的展开:
s/\b # Start with a word boundary, and
( # save away
[tT] # either a `t' or a `T',
) # stop saving,
eh # and then the rest of the word
\b # ending at a word boundary
/ # and replace it with
$1 # the original character we saved, whether `t' or `T'
he # and the correct spelling
/gx; # globally throughout the string.
正则表达式在看第一眼时会觉得很难,但是一旦你明白了,能像上面这样分解再重
新构建出来,你将会发现它就像用你自己的语言表达出来的一种自然的查找文本的
方式。指责正则表达式把 Perl 变复杂无疑是个谣言。
* 引用使 Perl 难学
这一条实际上是两个谣言。第一条是 Perl 不能处理复杂的数据结构。在 Perl 中
只有三种数据类型:标量用于保存数字和文档,看上去类似于 $foo;数组用于保存
一系列的标量,类似于 @bar;还有散列,保存一对一的标量关系,类似于 %baz。
散列通常用于存储“键-值”对类型。下面会举一些例子。
这不足以构建实际编程中需要的复杂数据结构。是的,它并非完全错误。但是从
Perl 5 开始,已经发布 5 年了 (本文写于 2000 年),Perl 已经可以用引用来构
建复杂的数据结构。
一旦你明白了这一点,你将听到另一个相反的意见:引用太复杂了,你将被那些标
点符号烦死。有趣的是,觉得引用太复杂的人通常是习惯于 C ── 引用类似于指针
,但是不是完全相同。在 C 里,人们总是要关心内存,地址等等不相干的东西,但
是在 Perl 里,你不用担心内存分配的问题,只要花时间考虑你那些更重要的事情
。C 程序员总是把事情搞得越来越复杂,把自己都搞晕了。
简单的说,引用就是对数据作压缩存储,把任意的数据──散列,数组,标量,甚至
子例程──都转变成一个标量来表示。比如我们有这样一些散列:
%billc = (
name => "Bill Clinton",
job => "US President"
);
%billg = (
name => "Bill Gates",
job => "Microsoft President"
);
为每个人都保存一个单独的变量显然太可怕了,世界上叫 Bill 的人那么多,我一
个月都能碰到四个。最理想的是能把他们都放在一起,所以我们需要把它们保存在
数组中。问题来了,数组只能保存标量,而不是散列。没有关系,把每个散列用一
个引用压缩到一个标量就行了。只需要简单的在名字前加上一个反斜线:
$billc_r = \%billc;
$billg_r = \%billg;
现在我们有两个标量,保存了所有的数据。要解压缩数据还原成散列,你需要去除
引用:告诉 perl 你想把它变成散列。我们知道散列是以 % 开头,所以在引用名字
前加上 % 就行了:
%billc 现在可以用 %$billc_r 来访问
%billg 现在可以用 %$billg_r 来访问
我们可以把引用保存在数组中:
@bills = ( $billc_r, $billg_r );
或者写成:
@bills = ( \%billc, \%billg );
你看,这就是一个包含两个散列的数组,一个复杂的数据结构。
当然,这有一点小窍门:怎样直接创建数组或散列的引用,而不是对已有变量进行
引用,以及怎样得到引用中的数据而不去解除引用。
但是正如前面所说,你不必学会语言的全部内容才把事情做好。是的,如果你不用
临时变量会使得代码更加整洁,简短,但是如果你不知道怎样做,丝毫不影响你使
用引用。
同样,可能你现在对引用还没有完全理解,你可能还没有认识到它们的用途,实际
上如果只是写一个简单的程序,你完全可以不用到引用。不管是说 Perl 不能处理
复杂数据,还是说引用太复杂,都是毫无根据的。
* Perl 是 Unix 专用
Perl 不是 Unix 专用吗?当我听到这个时,我都不禁想笑。标准的 Perl 发行版包
含超过对 70 种操作系统的支持。对于 Windows Macintosh 和许多操作系统都有专
门的移植项目。现在很难找到一台计算机不能运行 Perl:Perl 甚至可以在 Psion
organiser 上运行。
这意味着 Perl 即使不是最具可移植性的语言,也是它们中的一种。经过良好书写
的程序完全可以不作任何修改就能在 Unix 到 Windows NT 或 Macintosh 运行。写
的不好的,可能需要修改其中三四代码。
Perl 显然不是 Unix 专用。这是最没有根据的谣言。
* Perl 是 one-liner 专用──不能写真正的程序
说 Perl 只是脚本语言的人也会告诉你 Perl 不适合"严肃的编程"(serious
programming)。你不能用 Perl 来写一个操作系统,所以它没有什么用。
是的,你不会用它来写操作系统。但是我知道有那么一两个人正在尝试,他们有强
迫症。但是这并不表示你不能用 Perl 来写大型的、严格的、重要的程序。它是一
门编程语言。
人们已经写了不少很大的项目,比如 Slashdot,Human Genome Project。有成百上
千行代码的 Perl 程序并不少见。
而且,你还可以对任意 C 函数库扩展 Perl。你在 C 中可以作到的任意事情都能在
perl 中完成。它是 one-liner 和简单数据处理的理想语言,但这不是 perl 的全
部。
说 Perl 不适合严肃编程是对 Perl 或严肃编程的极大误解。
* Perl 是 CGI 专用
啊,这是著名的 CGI/Perl 混淆。由于 perl 是最合适作动态网页的语言,人们开
始对 Perl 和 CGI 的差别分不清了。
CGI 只是一个协议,用于让网络服务器和程序用同一种语言交流达成一致。你可以
让 Perl 执行这个协议,如果必需的话,你也可以让 C 来写 CGI。我还用
INTERCAL 写过 CGI。根本没有只针对 Perl 的 CGI。
当然也有 perl 特定的 CGI,因为太多人用 Perl 了,perl 又恰好适合做这件事。
但是正如我们看到的,人们可以并正在用 Perl 作更多的事情,不只是网络。
CGI 是 Perl?Perl 是 CGI?这都是谣言。
* Perl 太慢
也许你听到有人说 Perl 太慢了,没有任何用途。
在一些情况下,它相对于 C 来说是很慢,C 可能比相当的 Perl 程序快 50 倍,但
是这取决于许多因素。取决于你的程序是怎样写的,如果你是用 C 那样写 Perl 代
码,你将发现它会比用 Perl 风格的方式慢得多。比如,你对字符串进行一个字符
一个字符的检查,你将做很多事情,很可能一个简单的正则表达式就能解决问题。
你让 Perl 做的越少,它将运行的越快。
有时候,有些事情 C 很难完成,但是 Perl 却非常容易,比如字符串操作。 Perl
让你真正在字符串层面操作,而不是每次只看到一个字符。
有时候,C 确实在运行时有优势,但是如果你来写这个程序,它还需要考虑的是另
一个方面:开发时间。对你而言,时间和精力是很重要的,现在程序员是很花钱的
。
我们看一个非常简单的例子。在一个文档里有一串连续的数字,我们在第 50 行加
了一行,所以在第 50 行之后每一行都要加 1。我情愿花几分钟写下这样的 Perl
代码:
% perl -p -e 's/^(\d+)/1+$1/e if $. > 50'
也不愿花半小时写一个 C 程序。
我们可能对于这样简单的事情并不需要 C 的速度,对于大型程序这个原理也是一样
:你可能可能用 C 写一个跑得更快的程序,但是你总是可以用 Perl 更快的写出这
样的程序。
* Perl 不安全
首先源代码必需是能够读的,因为 Perl 解释器需要运行它,但是这不意味着 Perl
是不安全的。它只能说明你写的代码是不安全的,最好把这些漏洞都隐藏起来。但
是现在,很少有人和微软会同意这一点。通过不透明作为安全性手段是非常不安全
的。
就像你的代码的可读性和著名的 Y2K bug,你不能因为选择 Perl 而责怪 Perl。
Perl 不会确保你能写出安全的程序,如果你使用 tainting 机制的话,它会尽量阻
止你写不安全的代码,但是没有可以代替你来写代码。
如果你实在想让代码不可读的话,你也可以试着隐藏源代码,你可以使用源代码干
扰器,也可以用 Perl 编译器进行编译,但是它们不确保不会被解密或反编译。写
安全的代码是最好的办法。
所以你写的程序可能是不安全的,但是 Perl 本身就不安全了?不,这是另一个谣
言。
* Perl 不是商业化的,所以不好
最后,因为 Perl 不是商业软件,所以它不好。没有支持服务,文档是由志愿者提
供的,等等。
但是让我吃惊的是有 Linux 世界和 Apache、Samba 及许多成功的技术还有人这样
认为。然而我又想清楚了,这并不奇怪,因为商家们想让他们这样认为,并花了很
多钱让他们这样做。
因为有志愿者支持,人们因为爱而做这些事,而不是为了钱。这往往带来更好的产
品。
标准 Perl 发行版包含超过 70,000 行的文档,对于每个人都已经足够了。如果还
觉得不够的话,在网络上有无数的教程。加上 CPAN 模块的文档,我们已经有足够
的资源了。这些还只是免费的东西,据最新的统计,现在已经有超过 250 本专门讲
Perl 的书,很可能还有同样多的书提到了 Perl。
文档根本不是问题的所在。
至于支持,如果你读了所有文档还有问题的话,至少有 5 个 Usenet 新闻组是专门
针对 Perl 的,至少有一个 IRC 频道。这些都是志愿者做的,所以如果你没有仔细
读过 FAQ 的话,很可能他们会不客气地对你。但是不表示它们没有用,一些 Perl
世界里有名的人物都在这里出没。如果你有足够的常识的话,不难找到你问题的答
案。
当然,你可能还需要更多──数以千计的公司提供 Perl 培训,你可以购买真正的支
持服务,Perl 包和任何让难缠的老板都能满意的东西。不会因为它是免费的,就表
示它不能商业化,认为免费就没有价值显然是错误的。
* 结论
这不是全部你听说的关于 Perl 的谣言,我没有时间列出全部。如果你听过我提到
的这些,我请你再重新考虑一下 Perl,它会比你想的简单,会比你想的快,会比你
想的更好。不要轻信谣言,甚至不要相信我说的,自己试一试才行。
这是一条镜像帖。来源:北邮人论坛 / soft-design / #28050同步于 2008/7/11
该镜像源已超过 30 天没有更新,可能在源站已被删除。
SoftDesign机器人发帖
Ten Perl Myths
coolfantasy
2008/7/11镜像同步10 回复
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
我相信科学家的话
【 在 coolfantasy 的大作中提到: 】
: Perl 已经废了,与 Python、PHP 的差距会越来越大
: --
: 微博 http://t.sina.com.cn/coolfantasy
: ...................