C++lambda递归的三种写法

0x00问题引入

对于一个求自然数1-N和的问题,我们很容易写出以下递归公式:

f(n) = n == 1 ? 1 : n + f(n - 1);

若想使用C++lambda表达式实现上述过程,我们很容易将其改写为以下代码:

const auto& f = [](const int& n) {
	return n == 1 ? 1 : n + f(n - 1);
};

发现编译无法通过,为什么呢?原因是,由于lambda表达式的匿名特性,无法直接在lambda内部递归调用lambda,我们需要另寻其道来解决该问题。

0x01使用std::function

std::function可以把lambda包装起来,相当于赋予了其一个函数名,在通过引用捕获并实现递归调用,实现如下:

const auto& sum1 = [](const int& n) {
	std::function<int(const int&)>s;
	s = [&](const int& n) {
		return n == 1 ? 1 : n + s(n - 1);
	};
	return s(n);
};

0x02将lambda作为参数

先附上代码:

const auto& sum2 = [](const int& n) {
	const auto& s = [&](auto&& self, const int& x) -> int{
		return x == 1 ? 1 : x + self(self, x - 1);
	};
	return s(s,n);
};

注意到,调用s(s,n)时,我们把lambda表达式本身作为了参数传入来实现递归调用。

0x03使用Y组合子

构造一个Y组合子如下:

const auto& y = [](const auto& f) {
	return [&](const auto& x) {
		return x(x);
	}([&](const auto& x) -> std::function<int(int)> {
		return f([&](const int& n) {
			return x(x)(n);
		});
	});
};

再实现一个求和函数的高阶函数如下:

const auto& sum3 = [](const auto& f) {
	return [=](const int& n) {
		return n == 1 ? 1 : n + f(n - 1);
	};
};

然后连接即可。

0x04测试

在main中简单测试一下上述实现:

int main() {
	std::cout << sum1(100);//print 5050
	std::cout << sum2(100);//print 5050
	std::cout << y(sum3)(100);//print 5050
}

运行结果符合预期。

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值