2008-03
27

今天继续翻译代码布局的这一部分。有些很明显的条目,就不翻译了,看看代码就应该明白是什么意思。

阅读全文 »


2008-03
18

今天在写代码时遇到一个很奇怪的问题。我写的这样一个函数:

sub parse {
  my $self = shift;
  my $header = shift;
  my $charset = shift;
  
  # 其它处理
  # ...
}

至于如何调用,则是先通过 MIME::Parser 模块解析邮件, 然后调用解析结果中的 MIME::Head::get 函数来获得邮件头的值, 再将其结果传递给 parse 函数:

print $self->parse($head->get("Cc"), "GB2312");

通常都没有问题,在parse函数中,$header取到 Cc 邮件头,而 $charset 取到 "GB2312"; 但当一封邮件中不存在Cc时,就会出现一件怪事: $header 变量竟然取到了第二个参数 "GB2312" 的值!

在 parse 中将 @_ 打出来,发现当Cc邮件头取不到时,第一个参数就“消失”了, 参数列表就变成了 ("GB2312")。按照常理,参数列表应该是 (undef, "GB2312")才对啊。

百思不得其解中,偶然看到 MIME::Head::get 的文档中这样说:

  • If a numeric INDEX is given, returns the occurence at that index, or undef if not present:
  • If no INDEX is given, but invoked in a scalar context, then INDEX simply defaults to 0:
  • If no INDEX is given, and invoked in an array context, then all occurences of the field are returned:

上面的调用属于没有 INDEX 的情况,莫非parse函数的参数列表提供了一个列表环境, 导致MIME::Head::get返回了一个数组?

于是强制为它提供一个标量环境,结果就正常地得到了 (undef, "GB2312")。

print $self->parse(scalar $head->get("Cc"), "GB2312");

看来果然是上下文环境造成的问题。parse函数的第一个参数期待一个常量, 而函数的参数列表却是一个列表环境,再加上MIME::Head::get在列表环境中返回数组, 这样就会导致两种错误:

  • 如果不存在Cc,则参数列表为("GB2312"),$header = "GB2312";
  • 如果存在多个Cc,则参数列表为("Cc-val1", "Cc-val2", "Cc-val3", "GB2312"), $charset="Cc-val2"。

两种情况都十分荒谬。

对Perl的上下文不熟悉的人,这里可要特别注意啊。



2008-03
11

继续翻译Perl最佳实践的2.9~2.12。

阅读全文 »


2008-03
08

停止已久的《Perl Best Practices》翻译今天重新开始了。继续讲代码布局。

阅读全文 »


2008-01
29

上周偶然与fcicq讨论到一个关于perlcc的优化问题。 据说用perlcc将perl程序编译成C程序后再用gcc -O3进行优化,速度可能会快一些。 于是就测了测,顺便试了试其他语言的情况。

测试程序是Ackermann函数。 也许用它来做benchmark不太合适,但毕竟这是个纯数学+多次递归+耗时的运算,也能反映一定问题吧。

阅读全文 »

2007-12
14

那天和人讨论一个简单的应用:集合减法,即给定集合 A 和 B ,计算 C = A - B, 也就是说求属于A但不属于B的元素。集合A和B使用数组来存储,元素仅限于整数。 求计算方法。

Perl自身没有集合运算函数,为了这一个功能也犯不上去安装CPAN模块, 所以我们考虑了以下几个方案:

  1. 利用foreach作最直白的循环来判断
  2. 利用grep代替foreach
  3. 将元素用逗号连接之后用正则表达式匹配
  4. 将数组转化成散列之后判断

四种方法都能实现,但效率如何?本以为使用foreach应该是最快的, 没想到测试之后发现散列居然是最快的。

              Rate    use grep  use regexp use foreach    use hash
use grep     359/s          --        -58%        -63%        -90%
use regexp   861/s        140%          --        -11%        -77%
use foreach  965/s        169%         12%          --        -74%
use hash    3769/s        950%        338%        291%          --

如果元素不是整数而是随机的字符串,正则表达式的效率会急剧下降,而散列依然能保证领先的地位。 看来Perl的散列算法不可小觑啊。

阅读全文 »

2007-11
30

最近在阅读《Perl Best Practices》(Perl最佳实践)这本书。 Damian Conway这这本大作从各个方面 阐述了Perl编程上的一些经验,是Perl编程人员的必读之物。 标题上的PBP即Perl Best Practices的缩写。 鉴于这本书目前还没有中译本,我准备将这本书摘录一些翻译过来, 给各位Perler作为参考。

阅读全文 »

2007-10
12

我习惯于将照片按照拍摄时间保存到硬盘上的 YYYYMMDD 目录下,但每次都手工查看拍摄时间再建目录、复制实在是费时费力,于是写了这个程序,放在桌面上只要双击一下就可以将照片按照日期复制过来。当然只考虑了Win32版,估计我不太可能在Linux下用相机……需要安装ActivePerl,并用ppm安装Win32::DriveInfo模块。

照片复制程序

另外,我只有一台T10,所以这个程序只考虑了T10的情况,各位读者不妨说说自己的相机的目录结构?我的相机目录结构如下:

型号:SONY Cybershot T10
根目录:DCIM
照片目录:101MSDCF, 102MSDCF, 103MSDCF, …, 999MSDCF


2007-10
09

Test::Base是什么?用官方的说法是“数据驱动的测试”。Test::Base是一个测试框架, 只要给它提供测试数据,它就能自动进行单元测试,省却了手工编写测试程序的麻烦。

可能有人用过Test::More模块进行自动测试,那么我推荐你使用Test::Base。Test::Base 与Test::More完全兼容,也就是说你可以仅仅将use Test::More;换成use Test::Base; 而不用改动任何其他代码;其次,Test::Base可以提供更为简单的测试方法, 让你不必在繁琐的测试程序上花费时间。

阅读全文 »

2007-10
06

众所周知Perl 5的面向对象并不是真正意义上的面向对象, 只是添加了一些函数使得它看起来像是面向对象而已。 通常bless出来的对象,它的属性可以被外部程序直接访问。 《Perl Hacks》的#43给出了一个方法,可以封装类属性, 使其不能直接被外部访问。另外 Class::Std 模块可以简单地实现这个方法。

阅读全文 »