我对使用定点组合器的实际例子很感兴趣(比如C ++中的y-combinator。你有没有在现场使用egg或bind的定点组合器?码?
我在蛋中发现这个例子有点密集:
void egg_example()
{
using bll::_1;
using bll::_2;
int r =
fix2(
bll::ret<int>(
// \(f,a) -> a == 0 ? 1 : a * f(a-1)
bll::if_then_else_return( _2 == 0,
1,
_2 * lazy(_1)(_2 - 1)
)
)
) (5);
BOOST_CHECK(r == 5*4*3*2*1);
}
你能解释一下这一切是如何运作的吗?
是否有一个很好的简单示例,可能使用绑定的可能性比这个更少?
答案 0 :(得分:30)
这是转换为boost::bind
的相同代码,注意主函数中的y-combinator及其应用程序站点。我希望这会有所帮助。
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <iostream>
// Y-combinator compatible factorial
int fact(boost::function<int(int)> f,int v)
{
if(v == 0)
return 1;
else
return v * f(v -1);
}
// Y-combinator for the int type
boost::function<int(int)>
y(boost::function<int(boost::function<int(int)>,int)> f)
{
return boost::bind(f,boost::bind(&y,f),_1);
}
int main(int argc,char** argv)
{
boost::function<int(int)> factorial = y(fact);
std::cout << factorial(5) << std::endl;
return 0;
}
答案 1 :(得分:8)
#include <functional>
#include <iostream>
template <typename Lamba, typename Type>
auto y (std::function<Type(Lamba, Type)> f) -> std::function<Type(Type)>
{
return std::bind(f, std::bind(&y<Lamba, Type>, f), std::placeholders::_1);
}
int main(int argc,char** argv)
{
std::cout << y < std::function<int(int)>, int> ([](std::function<int(int)> f, int x) {
return x == 0 ? 1 : x * f(x - 1);
}) (5) << std::endl;
return 0;
}
答案 2 :(得分:3)
你能解释一下这一切是如何运作的吗?
fix2是一个y组合子(具体来说,它是具有两个参数的函数的组合子;第一个参数是函数(用于递归),第二个参数是“正确的”函数参数)。它创建递归函数。
bll :: ret(...)似乎创建了某种形式的函数对象,其主体是
if(second arg == 0)
{
return 1;
}
else
{
return second arg * first arg(second arg - 1);
}
“懒惰”可能是为了阻止第一个(函数)参数的无限扩展(阅读惰性和严格y组合子之间的区别以了解原因)。
代码非常可怕。匿名函数很不错,但是解决C ++缺乏语法支持的麻烦使它们不值得付出努力。