写点什么

柯里化与部分施用

作者:SkyFire
  • 2023-02-01
    陕西
  • 本文字数:1504 字

    阅读完需:约 5 分钟

什么是柯里化?

柯里化(Currying)是一种函数式编程技术,它的目的是将一个多参数的函数转换为一系列单参数函数,以达到减少代码量、提高代码可读性等目的。例如,一个函数 f (x, y, z)可以被柯里化为 f (x) (y) (z)。当调用 f (x) 时,将会返回一个函数,该函数接受一个参数 y,并返回一个函数,该函数接受一个参数 z,最后返回 f (x, y, z) 的结果。

什么是部分施用?

部分施用(Partial Application)是一种函数式编程技术,它的目的是将一个多参数的函数转换为一个只有部分参数的函数。部分施用可以让我们将一个多参数的函数封装成一个单参数的函数,并将另外的参数提前指定好,使得函数的使用更加灵活。例如,一个函数 f (x, y, z)可以被部分施用为 f(x, y),其中 y 已经被提前指定好。当调用 f(x, y) 时,将会返回一个函数,该函数接受一个参数 z,最后返回 f (x, y, z) 的结果。

两者区别是什么?

柯里化和部分施用都是函数式编程的技术,它们的目的都是将一个多参数的函数转换为一个更加灵活的函数,以减少代码量、提高代码可读性等。但是,它们有一个显著的区别:柯里化是将一个多参数的函数转换为一系列单参数函数,而部分施用是将一个多参数的函数转换为一个只有部分参数的函数,其中部分参数已经被提前指定。


可以说,柯里化是部分施用的一个特例。


柯里化的优点是可以减少函数的参数,同时也可以使函数的逻辑更清晰易懂。部分施用的优点是可以更灵活地处理函数参数,比如可以提前传入某些参数,也可以只传入部分参数,有助于函数重用。

使用 C++实现柯里化与部分施用

#include <functional>#include <iostream>
template <typename Result, typename Args1, typename... ArgsN>auto curry_helper(std::function<Result(Args1, ArgsN...)> f, Args1 a){ if constexpr (sizeof...(ArgsN) == 0) { return f(a); } else { return [f, a](ArgsN... args) { return f(a, args...); }; }}
template <typename F, typename Arg>auto curry(F f, Arg a){ return curry_helper(std::function(f), a);}
int calc(int a, int b, int c, int d, int e){ return a + b - c * d / e;}
int main(){ auto f1 = curry(calc, 5); auto f2 = curry(f1, 6); auto f3 = curry(f2, 7); auto f4 = curry(f3, 8); auto v = curry(f4, 9); std::cout << v << std::endl;}
复制代码


上面的例子中,curry 函数接受两个参数,第一个参数是一个函数,第二个参数为一个值。


curry 使用 std::function 封装函数,使其可以匹配到 curry_helper 模板函数。


在 curry_helper 函数中,判断如果后续没有尚未补全的参数,就返回一个函数,接受剩余参数。如果所有参数都补全了,就返回函数调用的结果。


再看一下部分施用的实现。


#include <functional>#include <iostream>
int calc(int a, int b, int c, int d, int e){ return a + b - c * d / e;}
auto pa(int a, int c, int e){ return [a, c, e](int b, int d) { return calc(a, b, c, d, e); };}
int main(){ auto f = pa(5, 7, 9); auto v = f(6, 8);
std::cout << v << std::endl;}
复制代码


可以看到,部分施用的特点就是可以替换任意数量、任意位置的参数,其他的参数作为返回函数的参数。


从上面的代码实例可以看出,柯里化是部分施用的特殊情况。

应用场景

柯里化和部分施用的主要应用是减少传递参数所需的函数调用次数。这有助于使代码更简洁高效,以及创建高阶函数(即将其他函数作为参数的函数)。柯里化和部分施用在 JavaScript 中很常用,因为它们允许创建可以使用不同参数重复使用的函数。

发布于: 刚刚阅读数: 3
用户头像

SkyFire

关注

这个cpper很懒,什么都没留下 2018-10-13 加入

会一点点cpp的苦逼码农

评论

发布
暂无评论
柯里化与部分施用_函数式编程_SkyFire_InfoQ写作社区