[Perl]认清上下文环境
今天在写代码时遇到一个很奇怪的问题。我写的这样一个函数:
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的上下文不熟悉的人,这里可要特别注意啊。