在Perl 5中,我们可以应用函数式编程技术(使用闭包,高阶函数,如map,grep等)。但功能构成怎么样?让我们说,在Haskell中,可以使用(。)函数
轻松完成map (negate . abs) [-3, 2, 4, -1, 5]
在Perl中,这个“点函数”的等价物是什么?
答案 0 :(得分:10)
可悲的是,我不知道Haskell。
但是函数组合本质上是将一个函数的输出作为参数放入下一个函数中。
output = (negate . abs)(input)
与output = negate(abs(input))
相同。在Perl中,parens通常是可选的,输入隐含在map
函数中,所以我们可以说
output = map (negate abs) list
现在只需将其转换为Perl语法,我们就有
my @output = map {- abs} (1,2,3);
用于数学/代数否定,
my @output = map {! abs} (1,2,3);
用于逻辑否定(当然与map {! $_} (1,2,3)
相同)。
答案 1 :(得分:9)
好的,首先让我们看看Haskell中的(。)函数签名:
(.) :: (b -> c) -> (a -> b) -> a -> c
这很容易像这样实现
foo :: (b -> c) -> (a -> b) -> a -> c
foo f g a = f(g a)
Perl中的实现可能如下所示
sub dot {
my $f = shift;
my $g = shift;
my $a = shift;
$f->( $g->($a) )
}
现在我们像这样实现函数negate
sub negate { - shift }
我们准备像这样使用它
my @foo = map { dot \&negate, sub{abs}, $_ } -2..2;
print join( ", ", @foo) . "\n";
但是从其他答案中可以看出,有更简单的方法可以做到这一点。所以你应该问自己的是,你为什么要这样做。 Haskel具有几个使函数组合真正有用的特性。然而,在Perl中,我感觉非常笨拙和尴尬。
如果您对Perl实际擅长的函数式编程感兴趣,我推荐Book Higher-Order Perl。
答案 2 :(得分:5)
我不确定这是你要求的答案:
sub negate { - $_[0] }
map { negate abs } -3, 2, 4, -1, 5
答案 3 :(得分:3)
sub compose {
my ( $f, $g ) = @_;
return sub { $f->( $g->( @_ )); };
}
sub negate (_) { - ( $_[0] // $_ // 0 ); }
my $neg_abs = compose( \&negate, \&CORE::abs );
my @negs = map { $neg_abs->( $_ ) } -3, 2, 4, -1, 5;
compose
将实现点函数的简单版本。但如上所述,除非您想将功能传输到其他位置,否则它不是特别需要的。