I am trying to write a sub that takes a coderef parameter. My unit does some initialization, calls coderef, then does some cleanup.
I need to call coderef using the same context (scalar, list, void context) that my sub was called into. The only way I can think of is something like this:
sub perform {
my ($self, $code) = @_;
my @ret;
my $ret;
if (not defined wantarray) {
$code->();
} elsif (wantarray) {
@ret = $code->();
} else {
$ret = $code->();
}
if (not defined wantarray) {
return;
} elsif (wantarray) {
return @ret;
} else {
return $ret;
}
}
Obviously there is a lot of redundancy in this code. Is there a way to reduce or eliminate any of these redundancies?
EDIT Later I realized that I needed to run $code->()in a block evalso that the cleanup would be done even if the code dies. Adding support for eval and combining the user502515 and cjm sentences is what I came up with.
sub perform {
my ($self, $code) = @_;
my $w = wantarray;
return sub {
my $error = $@;
die $error if $error;
return $w ? @_ : $_[0];
}->(eval { $w ? $code->() : scalar($code->()) });
}
, , , .