有没有办法在Perl中实现部分应用?
假设,我想做类似的事情:
sub each_file($arr, $op) {
$op->($_) for @{$arr};
...
}
sub each_line($op, $file) {
...
}
each_file($arr, each_line($op));
我想部分仅将each_line()
应用于$op
,因此它将成为一个新功能,可以传递给$each_file
,我如何用惯用的Perl表达?
答案 0 :(得分:1)
您可以使用两种方法组合在Perl中执行此操作:
返回函数引用的函数
闭包
示例:
sub each_file {
my ($arr, $line_fn) = @_;
$line_fn->($_) for @{$arr};
...
}
sub each_line {
my ($op, $file) = @_;
...
}
sub make_line_processor {
my ( $op ) = @_;
# This is closed over $op, which effectively becomes
# a constant for the returned function
my $fn = sub {
return each_line( $op, @_ );
};
return $fn;
}
# To call it:
each_file( $arr, make_line_processor($op) );
如果您不想直接$op
,但需要一些昂贵的获取方法,这可能是一种更有用的技术。在这种情况下,您只需计算一次派生值(在make_line_processor
函数中)并将其关闭。
答案 1 :(得分:1)
# given some $op as implied by your code snippet
each_file($arr, sub { each_line($op, shift) });
# shift op will be applied when anonymous sub { … } is called
(当您拨打$op
电话时,您的代码段并未完全清楚您想要each_line
的内容。通常情况下,提供小型工作程序会更好。)
答案 2 :(得分:0)
您可以将此功能上传到班级。然后你可以overload the subroutine dereference operator使它看起来像你的类真的是代码参考。
package Partial;
use overload '&{}' => \&call;
sub new {
my $class = shift;
my $code = shift;
bless {code => $code, args => \@_}, $class;
}
sub call {
my ($self) = @_;
return sub{ $self->{code}->(@{$self->{args}}, @_) }
}
然后您可以像这样使用它:
sub printArgs {
print join ", ", @_;
print "\n";
}
my $partial = Partial->new(\&printArgs, 'foo', 'bar');
$partial->('baz', 'bat');
# prints foo, bar, baz, bat