【发布时间】:2011-01-03 13:51:45
【问题描述】:
我正在尝试编写一个带有 coderef 参数的 sub。我的 sub 进行了一些初始化,调用了 coderef,然后进行了一些清理。
我需要使用调用我的 sub 的相同上下文(标量、列表、无效上下文)调用 coderef。我能想到的唯一方法是这样的:
sub perform {
my ($self, $code) = @_;
# do some initialization...
my @ret;
my $ret;
if (not defined wantarray) {
$code->();
} elsif (wantarray) {
@ret = $code->();
} else {
$ret = $code->();
}
# do some cleanup...
if (not defined wantarray) {
return;
} elsif (wantarray) {
return @ret;
} else {
return $ret;
}
}
显然,这段代码中存在大量冗余。有什么办法可以减少或消除这种冗余?
EDIT 后来我意识到我需要在eval 块中运行$code->(),以便即使代码死了也能运行清理。添加 eval 支持,并结合 user502515 和 cjm 的建议,这就是我想出的。
sub perform {
my ($self, $code) = @_;
# do some initialization...
my $w = wantarray;
return sub {
my $error = $@;
# do some cleanup...
die $error if $error; # propagate exception
return $w ? @_ : $_[0];
}->(eval { $w ? $code->() : scalar($code->()) });
}
这消除了冗余,但不幸的是,现在控制流有点难以遵循。
【问题讨论】:
-
我还应该指出,如果
do some cleanup...不是必需的,则整个函数可以简化为return $code->(),并且上下文将自动被调用的子例程继承。不幸的是,清理是必要的。 -
“执行”?这是马戏团的代码吗?
标签: perl