C++ 里面散发的咖喱味儿 - Currying函数式编程
大家好,最近几篇都在聊C++里面的函数式编程,今天我们继续就某一个点来深入聊一下,来聊聊在 C++ 中如何使用 std::bind
来实现函数式编程,尤其是柯里化(Currying)这个概念。如果你对 JavaScript 里的柯里化已经有所了解,那就更好了,我们会引用一些 JavaScript 的例子来帮助理解。
什么是柯里化(Currying)
柯里化简而言之,就是把一个接受多个参数的函数,变成一系列只接受一个参数的函数。例如,假设有一个函数 add(a, b)
,它接受两个参数并返回它们的和。那么柯里化之后的 add
变成了一个函数,接受一个参数 a
,再返回一个新的函数,这个新的函数再接受一个参数 b
,然后返回 a + b
的结果。
用 JavaScript 写个简单的例子:
function add(a) {
return function(b) {
return a + b;
}
}
const add5 = add(5);
console.log(add5(3)); // 输出 8
柯里化主要的好处是提高了函数的灵活性和可重用性,使得部分应用一个函数变得更加方便。
柯里化(Currying)的名字由来
Haskell Curry
这个概念之所以被称为“柯里化”,是因为它以逻辑学家 Haskell Curry 的名字命名。Haskell Curry 在数学和逻辑学领域做出了许多重要贡献,特别是在函数应用和组合子的研究上。
然而,尽管是 Curry 的名字被用于这个概念,但柯里化这个技术实际上是由另一个人提出的——Moses Schönfinkel。他在 1924 年提出了这个概念,不过后来是 Curry 把这个技术推广开来并使之广为人知。因此,为了纪念 Curry 的贡献,人们把这种技术命名为“Currying”。
有趣的是,Haskell Curry 这个名字在编程界还有另一个重要的关联——函数式编程语言 Haskell 也是以他的名字命名的。Haskell 语言本身就大量使用了柯里化等函数式编程的概念。
在 Haskell 这样纯函数式小众编程语言中,所有函数实际上都是柯里化的。这意味着一个多参数函数实际上是多个一元函数的嵌套。
add :: Int -> Int -> Int
add a b = a + b
add5 :: Int -> Int
add5 = add 5
main = print (add5 3) -- 输出 8
以上就是纯正的函数式编程,我断定会使用Haskell语言的小伙伴们应该寥寥无几,本人曾经为了准备一场笔试,曾在一个周末馒头苦学Haskell,强行消化各种晦涩的函数理念,以及递归编程范式,克服种种函数编程对传统的、面向对象的编程思想带来的冲击,才得以侥幸顺利通过。
什么是 std::bind
在 C++ 中,std::bind
是一个强大的工具,能够将函数与其部分参数绑定生成新的函数对象,这在需要部分应用函数、延迟调用以及函数式编程中非常有用。std::bind
可以与普通函数、成员函数、函数对象、以及 lambda 表达式一起使用,极大地提高了代码的灵活性和可重用性。
std::bind
位于 <functional>
头文件中,通过将函数或函数对象与参数进行绑定,生成一个新的可调用对象。其基本用法如下:
#include <functional>
auto bound_func = std::bind(函数或函数对象, 参数