我正在慢慢尝试使用Python进行函数编程,并遇到以下问题:
给定两个函数f1
和f2
,我该如何构造一个函数f,以相同的参数“以函数方式”将这两个函数相乘?
没花太多时间从事函数式编程,我确实有一个解决方案
f = lambda x : f1(x) * f2(x)
但是似乎不符合函数式编程的精神。
我的下一个尝试是像这样使用mul
和juxt
运算符
>>> from tools import juxt
>>> from operator import mul
>>> f = mul(juxt(f1,f2))
TypeError: op_mul expected 2 arguments, got 1
尝试用juxt
拆分*
的元组输出也不起作用:
>>> f = mul(*juxt(f1, f2))
TypeError: mul() argument after * must be an iterable, not juxt
再次使用lambda
似乎可行,但是以某种方式破坏了整个目标……
>>> temp = juxt(f_1, f_2)
>>> f = lambda x : mul(*temp(x))
也许我在这里对Python太过ped脚或太不客气了,但是我觉得我在函数式编程中缺少了一些非常重要或常规的东西。
是否有更实用的方法?
答案 0 :(得分:4)
TL; DR这种组合是Python和tools
模块都不支持的原始操作(从某种意义上说,不能将其分解为其他高阶函数)。您需要自己实施。
您所缺少的(或者更确切地说,Python和tools
模块所缺少的)是应用函子的概念。要了解 的含义,首先让我们回顾一下tools
模块中的两个功能:
compose
使您可以将两个功能链接在一起。也就是说,
compose(f,g) == lamba x: f(g(x))
curry
与部分应用有关:演示比解释快:
curry(f)(x)(y) == f(x, y)
也就是说,curry(f)(x)
与partial(f, x)
基本相同;两者都使用值y
来返回值f(x, y)
。
此外, functor 基本上是一种将函数映射到某个值的方法。您无疑对列表函子很熟悉:
map(f, [a,b,c]) == [f(a), f(b), f(c)]
函数也是 函数,但是我们使用map
代替compose
。也就是说,将f
映射到g
会产生compose(f, g)
。
现在,要将mul
,f1
和f2
合并为g = lambda x: g(f1(x), f2(x))
,似乎compose
和curry
都将是有用的。
lambda x: mul(f1(x), f2(x)) == lambda x: curry(mul)(f1(x))(f2(x))
和
lambda x: mul(f1(x), f2(x)) == lambda x: compose(curry(mul), f1)(x)(f2(x))
(也就是说,curry
使我们可以将另一个函数的两个参数组合在一起。)
但是,从某种意义上讲,合成严格上是 linear 操作;一个功能的输入来自另一个功能的输出。 mul
和f1
的组合创建了一个期望参数的函数,而返回了一个期望相同参数的函数。如何将x
从两个表达式的“中间”移出?我们需要一些
神秘功能foo
这样
foo(f, g) = lambda x: f(x, g(x))
生成一个函数,该函数将其参数同时传递给 f
和g
,同时还将结果g(x)
传递给f
。有了这样的功能foo
,我们可以编写
lambda x: foo(compose(curry(mul), f1), f2)
并获得我们想要的结果。
这使我们想到了 applicative 函子的概念。它提供了必要的功能foo
def foo(f, g):
def _(x):
return f(x, g(x))
结合了我们目前尚不具备的合成和计算概念。
换句话说,foo
是 distinct 的原始操作;您不能根据合成本身来实现它。
答案 1 :(得分:1)
如果您真的要对此类高阶函数使用运算符,则可以为其修饰符。
$("#buttonR").click(function(){
$(".changable").css({backgroundImage: "url("+ images[i % n].image +")" });
$("#changeText").text(images[i % n].name);
i++;
});